[[[ Add contrib/hook-scripts/precommit-pyfiles-notabs-properties.py Functions as a pre-commit hook script that does several things: * prevents committing any python file containing a tab character * checks if there are tabs in the source file and warns if so * aborts if incorrect properties of eol-style and keywords 'id' ]]]
This message, including any attachments, is the property of Sears Holdings Corporation and/or one of its subsidiaries. It is confidential and may contain proprietary or legally privileged information. If you are not the intended recipient, please delete it without reading the contents. Thank you.
Index: contrib/hook-scripts/precommit-pyfiles-notabs-properties.py =================================================================== --- contrib/hook-scripts/precommit-pyfiles-notabs-properties.py (revision 0) +++ contrib/hook-scripts/precommit-pyfiles-notabs-properties.py (working copy) @@ -0,0 +1,127 @@ +#!/bin/env python + +""" + pre-commit hook script that does several things: + * prevents committing any python file containing a tab character. + * checks if there are tabs in the source file and warns if so; + * aborts if incorrect properties of eol-style and keywords 'id'. +""" +import sys +import os +import traceback +from optparse import OptionParser + +#sys.stderr.write("NOTE: pre-commit hook script enabled - checks for tabs, svn eol-style and id properties...\n") + +def command_output(cmd): + " Capture a command's standard output. " + import subprocess + return subprocess.Popen( + cmd.split(), stdout=subprocess.PIPE).communicate()[0] + +def files_changed(look_cmd): + """ List the files added or updated by this transaction. + + "svnlook changed" gives output like: + U trunk/file1.cpp + A trunk/file2.py + """ + def filename(line): + return line[4:] + + def added_or_updated(line): + return line and line[0] in ("A", "U") + + retval = [] + for line in command_output(look_cmd % "changed").split("\n"): + if added_or_updated(line): + retval.append(filename(line)) + #sys.stderr.write("files changed: %s" % (retval)) + return retval + +def file_contents(filename, look_cmd): + " Return a file's contents for this transaction. " + return command_output("%s %s" % (look_cmd % "cat", filename)) + +def file_get_properties(filename, look_cmd): + propslines = command_output("%s %s" % (look_cmd % "proplist -v", filename)) + res = {} + for line in propslines.split('\n'): + line = line.strip() + if not line: + continue + k, v = line.split(' : ') + res[k] = v + return res + +def contains_tabs(filename, look_cmd): + " Return True if this version of the file contains tabs. " + return "\t" in file_contents(filename, look_cmd) + +def check_py_files(look_cmd): + " Check Python files in this transaction are tab-free. " + + def is_py_file(fname): + return os.path.splitext(fname)[1] == ".py" + + py_files_with_tabs = set() + py_files_bad_eolstyle = set() + py_files_bad_exec = set() + py_files_bad_keywords = set() + for ff in files_changed(look_cmd): + if not is_py_file(ff): + continue + if contains_tabs(ff, look_cmd): + py_files_with_tabs.add(ff) + props = file_get_properties(ff, look_cmd) + eolstyle = props.get('svn:eol-style') + #sys.stderr.write("props: %s\neolstyle: '%s'\n" % (props, eolstyle)) + if eolstyle in ('native', 'LFFFFF'): + py_files_bad_eolstyle.add(ff) + execut = props.get('svn:executable') + if execut not in ['ON', '*']: + py_files_bad_exec.add(ff) + keywords = props.get('svn:keywords') + if (not keywords) or ('Id' not in keywords.split()): + py_files_bad_keywords.add(ff) + + preventCommit = False + if len(py_files_with_tabs) > 0: + sys.stderr.write("The following files contain tabs:\n%s\n" % "\n".join(py_files_with_tabs)) + preventCommit = True + if len(py_files_bad_exec) > 0: + sys.stderr.write("The following py files are missing 'executable' property, committing anyway, but please fix this:\n%s\n" % "\n".join(py_files_bad_exec)) + # note, do not prevent commit over this, just warn. + if len(py_files_bad_keywords) > 0: + sys.stderr.write("The following files don't have keywords property set to 'Id' at least. Please fix this before committing:\n%s\n" % "\n".join(py_files_bad_keywords)) + preventCommit = True + if len(py_files_bad_eolstyle) > 0: + sys.stderr.write("The following files don't have svn propset svn:eol-style 'LF', please do so before committing:\n%s\n" % "\n".join(py_files_bad_eolstyle)) + preventCommit = True + + return preventCommit + +def main(): + usage = """usage: %prog REPOS TXN + Run pre-commit options on a repository transaction.""" + + parser = OptionParser(usage=usage) + parser.add_option("-r", "--revision", + help="Test mode. TXN actually refers to a revision.", + action="store_true", default=False) + errors = 0 + try: + (opts, (repos, txn_or_rvn)) = parser.parse_args() + look_opt = ("--transaction", "--revision")[opts.revision] + look_cmd = "svnlook %s %s %s %s" % ( + "%s", repos, look_opt, txn_or_rvn) + errors += check_py_files(look_cmd) + except: + parser.print_help() + errors += 1 + sys.stderr.write("Pre-commit hook traceback: %s" % (traceback.format_exc())) + return errors + +if __name__ == "__main__": + sys.exit(main()) + Property changes on: contrib/hook-scripts/precommit-pyfiles-notabs-properties.py ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +Id \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +LF \ No newline at end of property Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property