123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- """
- Best-practices tracker for Tor source code.
- Go through the various .c files and collect metrics about them. If the metrics
- violate some of our best practices and they are not found in the optional
- exceptions file, then log a problem about them.
- We currently do metrics about file size, function size and number of includes.
- practracker.py should be run with its second argument pointing to the Tor
- top-level source directory like this:
- $ python3 ./scripts/maint/practracker/practracker.py .
- The exceptions file is meant to be initialized once with the current state of
- the source code and then get saved in the repository for ever after:
- $ python3 ./scripts/maint/practracker/practracker.py . > ./scripts/maint/practracker/exceptions.txt
- """
- from __future__ import print_function
- import os, sys
- import metrics
- import util
- import problem
- EXCEPTIONS_FNAME = "./exceptions.txt"
- MAX_FILE_SIZE = 3000
- MAX_FUNCTION_SIZE = 100
- MAX_INCLUDE_COUNT = 50
- ProblemVault = None
- TOR_TOPDIR = None
- if sys.version_info[0] <= 2:
- def open_file(fname):
- return open(fname, 'r')
- else:
- def open_file(fname):
- return open(fname, 'r', encoding='utf-8')
- def consider_file_size(fname, f):
- """Consider file size issues for 'f' and return True if a new issue was found"""
- file_size = metrics.get_file_len(f)
- if file_size > MAX_FILE_SIZE:
- p = problem.FileSizeProblem(fname, file_size)
- return ProblemVault.register_problem(p)
- return False
- def consider_includes(fname, f):
- """Consider #include issues for 'f' and return True if a new issue was found"""
- include_count = metrics.get_include_count(f)
- if include_count > MAX_INCLUDE_COUNT:
- p = problem.IncludeCountProblem(fname, include_count)
- return ProblemVault.register_problem(p)
- return False
- def consider_function_size(fname, f):
- """Consider the function sizes for 'f' and return True if a new issue was found"""
- found_new_issues = False
- for name, lines in metrics.get_function_lines(f):
-
- if lines <= MAX_FUNCTION_SIZE:
- continue
-
- canonical_function_name = "%s:%s()" % (fname, name)
- p = problem.FunctionSizeProblem(canonical_function_name, lines)
- found_new_issues |= ProblemVault.register_problem(p)
- return found_new_issues
- def consider_all_metrics(files_list):
- """Consider metrics for all files, and return True if new issues were found"""
- found_new_issues = False
- for fname in files_list:
- with open_file(fname) as f:
- found_new_issues |= consider_metrics_for_file(fname, f)
- return found_new_issues
- def consider_metrics_for_file(fname, f):
- """
- Consider the various metrics for file with filename 'fname' and file descriptor 'f'.
- Return True if we found new issues.
- """
-
- if fname.startswith(TOR_TOPDIR):
- fname = fname[len(TOR_TOPDIR):]
- found_new_issues = False
-
- found_new_issues |= consider_file_size(fname, f)
-
- f.seek(0)
- found_new_issues |= consider_includes(fname, f)
-
- f.seek(0)
- found_new_issues |= consider_function_size(fname, f)
- return found_new_issues
- def main():
- if (len(sys.argv) != 2):
- print("Usage:\n\t$ practracker.py <tor topdir>\n\t(e.g. $ practracker.py ~/tor/)")
- return
- global TOR_TOPDIR
- TOR_TOPDIR = sys.argv[1]
- exceptions_file = os.path.join(TOR_TOPDIR, "scripts/maint/practracker", EXCEPTIONS_FNAME)
-
- files_list = util.get_tor_c_files(TOR_TOPDIR)
-
-
- global ProblemVault
- ProblemVault = problem.ProblemVault(exceptions_file)
-
- found_new_issues = consider_all_metrics(files_list)
-
- if (found_new_issues):
- new_issues_str = """\
- FAILURE: practracker found new problems in the code: see warnings above.
- Please fix the problems if you can, and update the exceptions file
- ({}) if you can't.
- See doc/HACKING/HelpfulTools.md for more information on using practracker.\
- """.format(exceptions_file)
- print(new_issues_str)
- sys.exit(found_new_issues)
- if __name__ == '__main__':
- main()
|