/usr/share/subversion/hook-scripts/log-police.py is in subversion-tools 1.6.17dfsg-3ubuntu3.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | #!/usr/bin/python
# log-police.py: Ensure that log messages end with a single newline.
# See usage() function for details, or just run with no arguments.
import os
import sys
import getopt
try:
my_getopt = getopt.gnu_getopt
except AttributeError:
my_getopt = getopt.getopt
import svn
import svn.fs
import svn.repos
import svn.core
def fix_log_message(log_message):
"""Return a fixed version of LOG_MESSAGE. By default, this just
means ensuring that the result ends with exactly one newline and no
other whitespace. But if you want to do other kinds of fixups, this
function is the place to implement them -- all log message fixing in
this script happens here."""
return log_message.rstrip() + "\n"
def fix_txn(fs, txn_name):
"Fix up the log message for txn TXN_NAME in FS. See fix_log_message()."
txn = svn.fs.svn_fs_open_txn(fs, txn_name)
log_message = svn.fs.svn_fs_txn_prop(txn, "svn:log")
if log_message is not None:
new_message = fix_log_message(log_message)
if new_message != log_message:
svn.fs.svn_fs_change_txn_prop(txn, "svn:log", new_message)
def fix_rev(fs, revnum):
"Fix up the log message for revision REVNUM in FS. See fix_log_message()."
log_message = svn.fs.svn_fs_revision_prop(fs, revnum, 'svn:log')
if log_message is not None:
new_message = fix_log_message(log_message)
if new_message != log_message:
svn.fs.svn_fs_change_rev_prop(fs, revnum, "svn:log", new_message)
def usage_and_exit(error_msg=None):
"""Write usage information and exit. If ERROR_MSG is provide, that
error message is printed first (to stderr), the usage info goes to
stderr, and the script exits with a non-zero status. Otherwise,
usage info goes to stdout and the script exits with a zero status."""
import os.path
stream = error_msg and sys.stderr or sys.stdout
if error_msg:
stream.write("ERROR: %s\n\n" % error_msg)
stream.write("USAGE: %s [-t TXN_NAME | -r REV_NUM | --all-revs] REPOS\n"
% (os.path.basename(sys.argv[0])))
stream.write("""
Ensure that log messages end with exactly one newline and no other
whitespace characters. Use as a pre-commit hook by passing '-t TXN_NAME';
fix up a single revision by passing '-r REV_NUM'; fix up all revisions by
passing '--all-revs'. (When used as a pre-commit hook, may modify the
svn:log property on the txn.)
""")
sys.exit(error_msg and 1 or 0)
def main(ignored_pool, argv):
repos_path = None
txn_name = None
rev_name = None
all_revs = False
try:
opts, args = my_getopt(argv[1:], 't:r:h?', ["help", "all-revs"])
except:
usage_and_exit("problem processing arguments / options.")
for opt, value in opts:
if opt == '--help' or opt == '-h' or opt == '-?':
usage_and_exit()
elif opt == '-t':
txn_name = value
elif opt == '-r':
rev_name = value
elif opt == '--all-revs':
all_revs = True
else:
usage_and_exit("unknown option '%s'." % opt)
if txn_name is not None and rev_name is not None:
usage_and_exit("cannot pass both -t and -r.")
if txn_name is not None and all_revs:
usage_and_exit("cannot pass --all-revs with -t.")
if rev_name is not None and all_revs:
usage_and_exit("cannot pass --all-revs with -r.")
if rev_name is None and txn_name is None and not all_revs:
usage_and_exit("must provide exactly one of -r, -t, or --all-revs.")
if len(args) != 1:
usage_and_exit("only one argument allowed (the repository).")
repos_path = svn.core.svn_path_canonicalize(args[0])
# A non-bindings version of this could be implemented by calling out
# to 'svnlook getlog' and 'svnadmin setlog'. However, using the
# bindings results in much simpler code.
fs = svn.repos.svn_repos_fs(svn.repos.svn_repos_open(repos_path))
if txn_name is not None:
fix_txn(fs, txn_name)
elif rev_name is not None:
fix_rev(fs, int(rev_name))
elif all_revs:
# Do it such that if we're running on a live repository, we'll
# catch up even with commits that came in after we started.
last_youngest = 0
while True:
youngest = svn.fs.svn_fs_youngest_rev(fs)
if youngest >= last_youngest:
for this_rev in range(last_youngest, youngest + 1):
fix_rev(fs, this_rev)
last_youngest = youngest + 1
else:
break
if __name__ == '__main__':
sys.exit(svn.core.run_app(main, sys.argv))
|