def main(): global TAB_WIDTH git_exec = Git() output = git_exec.rev_parse('--show-toplevel', with_extended_output=True, with_exceptions=False) err_no, git_root, err_msg = output if err_no: print >> sys.stderr, err_msg sys.exit(1) git_repo = Repo(git_root) git_config = git_repo.config_reader() ws_config = { 'blank-at-eol': True, 'space-before-tab': True, 'indent-with-non-tab': False, 'tab-in-indent': False, 'blank-at-eof': False, 'trailing-space': False, 'cr-at-eol': False, } try: _config_whitespace = git_config.get('core', 'whitespace') for c in _config_whitespace.split(','): c = c.strip() if 'tabwidth' in c: ws_config['tabwidth'] = int(c.split('=').pop()) else: if c[0] == '-': # e.g. -tab-in-indent ws_config[c[1:]] = False else: ws_config[c] = True except: pass if ws_config.get('tab-in-indent', False) and \ ws_config.get('indent-with-non-tab', False): print >> sys.stderr, \ 'Cannot enforce both tab-in-indent and indent-with-non-tab.' sys.exit(1) TAB_WIDTH = ws_config.get('tabwidth') sanitizers = [] if ws_config.get('trailing-space', False): ws_config['blank-at-eol'] = True ws_config['blank-at-eof'] = True # Allow overrides gitconfig by cli argument arg_parser = argparse.ArgumentParser() arg_parser.set_defaults(**ws_config) arg_parser.add_argument('--trailing-space', dest='trailing-space', type=ast.literal_eval, metavar='True|False', help='trailing-space is a short-hand to cover ' 'both blank-at-eol and blank-at-eof') arg_parser.add_argument('--blank-at-eol', dest='blank-at-eol', type=ast.literal_eval, metavar='True|False', help='treats trailing whitespaces at the end of ' 'the line as an error') arg_parser.add_argument('--space-before-tab', dest='space-before-tab', type=ast.literal_eval, metavar='True|False', help='treats a space character that appears ' 'immediately before a tab character in the ' 'initial indent part of the line as an error') arg_parser.add_argument('--indent-with-non-tab', dest='indent-with-non-tab', type=ast.literal_eval, metavar='True|False', help='treats a line that is indented with 8 or ' 'more space characters as an error') arg_parser.add_argument('--tab-in-indent', dest='tab-in-indent', type=ast.literal_eval, metavar='True|False', help='treats a tab character in the initial ' 'indent part of the line as an error') # arg_parser.add_argument('--blank-at-eof', dest='blank-at-eof', # type=ast.literal_eval, metavar='True|False', # help='treats blank lines added at the end of ' # 'file as an error') arg_parser.add_argument('--cr-at-eol', dest='cr-at-eol', type=ast.literal_eval, metavar='True|False', help='treats a carriage-return at the end of ' 'line as part of the line terminator, i.e. ' 'with it, trailing-space does not trigger ' 'if the character before such a ' 'carriage-return is not a whitespace') arg_parser.add_argument('--tabwidth', type=int, metavar='', help='tells how many character positions a tab ' 'occupies; this is relevant for ' 'indent-with-non-tab and when git fixes ' 'tab-in-indent errors. The default tab ' 'width is 8.') arg_parser.add_argument('-d', '--debug', action='store_true', help='Print the whitespace config') args = arg_parser.parse_args() ws_config = vars(args) if args.debug: import pprint pp = pprint.PrettyPrinter() pp.pprint(ws_config) # Prepare appropriate sanitizers if ws_config.get('blank-at-eol', False): sanitizers.append(blank_at_eol_sanitizer) if ws_config.get('space-before-tab', False): sanitizers.append(space_before_tab_sanitizer) if ws_config.get('indent-with-non-tab', False): sanitizers.append(indent_with_non_tab_sanitizer) if ws_config.get('tab-in-indent', False): sanitizers.append(tab_in_indent_sanitizer) # if ws_config.get('blank-at-eof', False): # sanitizers.append(blank_at_eof_sanitizer) if ws_config.get('cr-at-eol', False): sanitizers.append(cr_at_eol_sanitizer) head_diff = git_repo.head.commit.diff(create_patch=True) head_diff_add = head_diff.iter_change_type('A') head_diff_modify = head_diff.iter_change_type('M') map(lambda i: sanitize_diff(i, git_root, sanitizers), itertools.chain(head_diff_add, head_diff_modify))