#!/usr/bin/env python ''' A script suitable for use as a git pre-commit hook to ensure your files are flake8-compliant before committing them. Use this by copying it to a file called $ARDUPILOT_ROOT/.git/hooks/pre-commit AP_FLAKE8_CLEAN ''' import os import re import sys import subprocess class PreCommitFlake8(object): def __init__(self): pass def progress(self, message): print("***** %s" % (message, )) def check_file(self, filepath): content = open(filepath).read() if "AP_FLAKE8_CLEAN" not in content: return True self.progress("Checking (%s)" % filepath) retcode = subprocess.call(["flake8", filepath]) if retcode != 0: self.progress("File (%s) failed with retcode (%s)" % (filepath, retcode)) return False return True def split_git_diff_output(self, output): '''split output from git-diff into a list of (status, filepath) tuples''' ret = [] if type(output) == bytes: output = output.decode('utf-8') for line in output.split("\n"): if len(line) == 0: continue ret.append(re.split(r"\s+", line)) return ret def run(self): # generate a list of files which have changes not marked for commit output = subprocess.check_output([ "git", "diff", "--name-status"]) dirty_list = self.split_git_diff_output(output) dirty = set() for (status, dirty_filepath) in dirty_list: dirty.add(dirty_filepath) # check files marked for commit: output = subprocess.check_output([ "git", "diff", "--cached", "--name-status"]) output_tuples = self.split_git_diff_output(output) self.retcode = 0 for output_tuple in output_tuples: if len(output_tuple) > 2: if output_tuple[0].startswith('R'): # rename, check destination (status, filepath) = (output_tuple[0], output_tuple[2]) else: raise ValueError("Unknown status %s" % str(output_tuple[0])) else: (status, filepath) = output_tuple if filepath in dirty: self.progress("WARNING: (%s) has unstaged changes" % filepath) if status == 'D': # don't check deleted files continue (base, extension) = os.path.splitext(filepath) if extension != ".py": continue if not self.check_file(filepath): self.retcode = 1 return self.retcode if __name__ == '__main__': precommit = PreCommitFlake8() sys.exit(precommit.run())