Skip to content

Commit 7366ca6

Browse files
committed
Various commit hooks in use currently.
- Legacy-Id: 10557
1 parent 063d92b commit 7366ca6

5 files changed

Lines changed: 760 additions & 0 deletions

File tree

hooks/post-commit

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#!/bin/bash
2+
3+
# POST-COMMIT HOOK
4+
#
5+
# The post-commit hook is invoked after a commit. Subversion runs
6+
# this hook by invoking a program (script, executable, binary, etc.)
7+
# named 'post-commit' (for which this file is a template) with the
8+
# following ordered arguments:
9+
#
10+
# [1] REPOS-PATH (the path to this repository)
11+
# [2] REV (the number of the revision just committed)
12+
#
13+
# The default working directory for the invocation is undefined, so
14+
# the program should set one explicitly if it cares.
15+
#
16+
# Because the commit has already completed and cannot be undone,
17+
# the exit code of the hook program is ignored. The hook program
18+
# can use the 'svnlook' utility to help it examine the
19+
# newly-committed tree.
20+
#
21+
# On a Unix system, the normal procedure is to have 'post-commit'
22+
# invoke other programs to do the real work, though it may do the
23+
# work itself too.
24+
#
25+
# Note that 'post-commit' must be executable by the user(s) who will
26+
# invoke it (typically the user httpd runs as), and that user must
27+
# have filesystem-level permission to access the repository.
28+
#
29+
# On a Windows system, you should name the hook program
30+
# 'post-commit.bat' or 'post-commit.exe',
31+
# but the basic idea is the same.
32+
#
33+
# The hook program typically does not inherit the environment of
34+
# its parent process. For example, a common problem is for the
35+
# PATH environment variable to not be set to its usual value, so
36+
# that subprograms fail to launch unless invoked via absolute path.
37+
# If you're having unexpected problems with a hook program, the
38+
# culprit may be unusual (or missing) environment variables.
39+
#
40+
# Here is an example hook script, for a Unix /bin/sh interpreter.
41+
# For more examples and pre-written hooks, see those in
42+
# the Subversion repository at
43+
# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
44+
# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
45+
46+
# Log everything for debug, otherwise use explicit logging (further down)
47+
#[ "$LOGGING" ] || LOGGING=1 { exec $0 "$@" 2>&1 | logger -p local0.info -t "commit"; }
48+
49+
logger -p local0.info -t "hook" "${0##*/} $*"
50+
51+
repo="$1"
52+
rev="$2"
53+
54+
# Settings
55+
program=${0##*/}
56+
progdir=${0%/*}
57+
thishost="$(/bin/hostname)"
58+
thishost="${thishost%%.*}"
59+
svnpath="/home/svn"
60+
trac="/www/tools.ietf.org/tools/ietfdb/"
61+
svn_url="https://svn.tools.ietf.org/svn/tools/ietfdb"
62+
trac_url="https://trac.tools.ietf.org/tools/ietfdb"
63+
64+
# Do a local backup
65+
relpath=${repo#$svnpath/}
66+
bckpath="$svnpath/.backup/$thishost/$relpath"
67+
[ -d $bckpath ] || mkdir -p $bckpath
68+
/usr/bin/svn-fast-backup -q $repo $bckpath
69+
70+
# Inform trac about a new changeset
71+
trac-admin $trac changeset added ietfdb $rev
72+
73+
committer=$(/usr/bin/svnlook author $repo -r $rev)
74+
comments=$(/usr/bin/svnlook log $repo -r $rev)
75+
files=$(/usr/bin/svnlook changed $repo -r $rev)
76+
77+
dirs=$(/usr/bin/svnlook dirs-changed -r$rev $repo)
78+
logger -p local0.info -t "commit" "dirs '$dirs'"
79+
80+
# Look for 'requirements.txt' above the committed change. Looking only for
81+
# filechanges, not for dirchanges, filters out commits which are just tree
82+
# copies, such as when creating new dev branches for the code sprint.
83+
branch=$($progdir/svnfind --filechange --dirpath $repo $rev "requirements.txt")
84+
85+
if [ -n "$branch" ]; then
86+
# Update trac tickets
87+
/usr/bin/python $progdir/trac-post-commit-hook -p "$trac" -r "$rev" 2>&1 | logger -t "svn post-commit" -p "user.error" -i
88+
89+
# Notify buildbot
90+
filenames=$(/usr/bin/svnlook changed $repo -r $rev | sed -r -e 's/^ *[^ ]+ +//' -e "s|$branch/||")
91+
/usr/local/bin/buildbot sendchange \
92+
--master="zinfandel.tools.ietf.org:9989" --auth="ietfdb:BRiR6XcT7x3$" \
93+
--who="$committer" --repository="https://svn.tools.ietf.org/svn/tools/ietfdb/" \
94+
--vc=svn --branch="$branch" --revision=$rev --property=xproperty:xvalue \
95+
--revlink="https://trac.tools.ietf.org/tools/ietfdb/changeset/$rev" \
96+
--comments="$comments" $filenames > /dev/null
97+
98+
fi
99+
100+
101+
# Log the commit
102+
logger -p local0.info -t "commit" "$relpath r$rev $committer"
103+
logger -p local0.info -t "commit" "branch: $branch"
104+
105+
# Notify committers
106+
107+
if [[ $comments =~ ready.(for|to).merge ]]; then
108+
mail $(< $progdir/notify-email.txt) -s "[svnhook] Svn commit ready for merge: $relpath | $committer: ${comments:0:42}..." <<-EOF | logger -p local0.info -t "ready for merge email"
109+
110+
$committer has a commit ready for merge:
111+
$relpath/$branch [$rev]:
112+
113+
$comments
114+
115+
Svn: $svn_url/$branch
116+
Trac: $trac_url/changeset/$rev/$branch
117+
118+
Files:
119+
120+
$files
121+
122+
EOF
123+
124+
else
125+
126+
mail $(< $progdir/notify-email.txt) -s "[svnhook] Svn commit to $relpath | $committer: ${comments:0:42}..." <<-EOF | logger -p local0.info -t "commit email"
127+
128+
$committer has made a new SVN commit in
129+
$relpath/$branch [$rev]:
130+
131+
$comments
132+
133+
Svn: $svn_url/$branch
134+
Trac: $trac_url/changeset/$rev/$branch
135+
136+
Files:
137+
138+
$files
139+
140+
EOF
141+
142+
fi

hooks/pre-commit

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#!/usr/bin/env python
2+
3+
"""
4+
An SVN pre-commit hook which requires that commits either are marked as
5+
whitespace cleanup commits, and contain no non-whitespace changes, or
6+
leave whitespace alone on lines without code changes.
7+
"""
8+
9+
import os
10+
import sys
11+
import difflib
12+
import debug
13+
from pysvn import Client, Transaction
14+
15+
prog = os.path.basename(sys.argv[0])
16+
17+
def die(msg):
18+
sys.stderr.write("\n%s: Error: %s\n" % (prog, msg))
19+
sys.exit(1)
20+
21+
if len(sys.argv) <= 1:
22+
die("Expected arguments: REPOSITORY TRANSACTION, found none")
23+
24+
if len(sys.argv) <= 2:
25+
die( "Expected arguments: REPOSITORY TRANSACTION, found only '%s'" % sys.argv[1])
26+
27+
repo = sys.argv[1]
28+
txname = sys.argv[2]
29+
tx = Transaction(repo, txname)
30+
client = Client()
31+
32+
is_whitespace_cleanup = "whitespace cleanup" in tx.revpropget("svn:log").lower()
33+
34+
def normalize(s):
35+
return s.rstrip().expandtabs()
36+
37+
def normalize_sequence(seq):
38+
o = []
39+
for l in seq:
40+
o.append(normalize(l))
41+
return o
42+
43+
def count(gen):
44+
return sum(1 for _ in gen)
45+
46+
# Function with side effects. Acts on global varaibles
47+
def inc_ab(flag):
48+
global a, b
49+
if flag == ' ':
50+
a += 1; b += 1
51+
elif flag == '-':
52+
a += 1
53+
elif flag == '+':
54+
b += 1
55+
elif flag == '?':
56+
pass
57+
else:
58+
raise ValueError("Unexpected ndiff mark: '%s' in: %s" % (flag, plain_diff[i]))
59+
60+
def get_chunks(unidiff):
61+
if not unidiff:
62+
return []
63+
chunks = []
64+
chunk = []
65+
intro = unidiff[0:2]
66+
for line in unidiff[2:]:
67+
if line.startswith("@@"):
68+
if chunk:
69+
chunks.append(chunk)
70+
chunk = [line]
71+
else:
72+
chunk.append(line)
73+
chunks.append(chunk)
74+
return intro, chunks
75+
76+
changes = tx.changed()
77+
issues = {}
78+
context = 3
79+
for path in changes:
80+
action, kind, mod, propmod = changes[path]
81+
82+
# Don't try to diff added or deleted files, on ly changed text files
83+
if not (mod and action == "R"):
84+
continue
85+
86+
# Don't try do diff binary files
87+
mimetype = tx.propget("svn:mime-type", path)
88+
if mimetype and not mimetype.startswith("text/"):
89+
continue
90+
91+
new = tx.cat(path).splitlines()
92+
old = client.cat("file://"+os.path.join(repo,path)).splitlines()
93+
94+
plain_diff = list(difflib.unified_diff(old, new, "%s (repository)"%path, "%s (commit)"%path, lineterm="" ))
95+
old = normalize_sequence(old)
96+
new = normalize_sequence(new)
97+
white_diff = list(difflib.unified_diff(old, new, "%s (repository)"%path, "%s (commit)"%path, lineterm=""))
98+
99+
plain_count = len(plain_diff)
100+
white_count = len(white_diff)
101+
102+
# for i in range(len(white_diff)):
103+
# sys.stderr.write("%-80s | %-80s\n" % (normalize(plain_diff[i][:80]), normalize(white_diff[i][:80])))
104+
if white_count != plain_count and not is_whitespace_cleanup:
105+
intro, plain_chunks = get_chunks(plain_diff)
106+
intro, white_chunks = get_chunks(white_diff)
107+
for chunk in white_chunks:
108+
for i in range(len(plain_chunks)):
109+
if chunk == plain_chunks[i]:
110+
del plain_chunks[i]
111+
issue = intro
112+
for chunk in plain_chunks:
113+
issue += chunk
114+
if len(plain_chunks) > 1:
115+
are = "are"; s = "s"; an = ""
116+
else:
117+
are = "is"; s = ""; an = "an "
118+
issues[path] = issue
119+
if white_count != 0 and is_whitespace_cleanup:
120+
intro, white_chunks = get_chunks(white_diff)
121+
if len(white_chunks) > 1:
122+
are = "are"; s = "s"; an = ""
123+
else:
124+
are = "is"; s = ""; an = "an "
125+
issues[path] = white_diff
126+
127+
if issues:
128+
if is_whitespace_cleanup:
129+
die("It looks as if there are non-whitespace changes in\n"
130+
"this commit, but it was marked as a whitespace cleanup commit.\n\n"
131+
"Here %s the diff chunk%s with unexpected change%s:\n\n%s\n\n"
132+
"Declining the commit due to a mix of code and spaces-only changes. Please\n"
133+
"avoid mixing whitespace-only changes with code changes. See details above." %
134+
(are, s, s, '\n\n'.join([ '\n'.join(issues[path]) for path in issues ]))
135+
)
136+
137+
else:
138+
die("It looks as if there are spaces-only changes in this\n"
139+
"commit, but it was not marked as a whitespace cleanup commit.\n\n"
140+
"Here %s the diff chunk%s with unexpected change%s:\n\n%s\n\n"
141+
"Declining the commit due to a mix of code and spaces-only changes. Please\n"
142+
"avoid mixing whitespace-only changes with code changes. See details above." %
143+
(are, s, s, '\n\n'.join([ '\n'.join(issues[path]) for path in issues ]))
144+
)
145+
146+
sys.exit(0)

hooks/pre-revprop-change

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/bin/sh
2+
3+
# PRE-REVPROP-CHANGE HOOK
4+
#
5+
# The pre-revprop-change hook is invoked before a revision property
6+
# is added, modified or deleted. Subversion runs this hook by invoking
7+
# a program (script, executable, binary, etc.) named 'pre-revprop-change'
8+
# (for which this file is a template), with the following ordered
9+
# arguments:
10+
#
11+
# [1] REPOS-PATH (the path to this repository)
12+
# [2] REVISION (the revision being tweaked)
13+
# [3] USER (the username of the person tweaking the property)
14+
# [4] PROPNAME (the property being set on the revision)
15+
# [5] ACTION (the property is being 'A'dded, 'M'odified, or 'D'eleted)
16+
#
17+
# [STDIN] PROPVAL ** the new property value is passed via STDIN.
18+
#
19+
# If the hook program exits with success, the propchange happens; but
20+
# if it exits with failure (non-zero), the propchange doesn't happen.
21+
# The hook program can use the 'svnlook' utility to examine the
22+
# existing value of the revision property.
23+
#
24+
# WARNING: unlike other hooks, this hook MUST exist for revision
25+
# properties to be changed. If the hook does not exist, Subversion
26+
# will behave as if the hook were present, but failed. The reason
27+
# for this is that revision properties are UNVERSIONED, meaning that
28+
# a successful propchange is destructive; the old value is gone
29+
# forever. We recommend the hook back up the old value somewhere.
30+
#
31+
# On a Unix system, the normal procedure is to have 'pre-revprop-change'
32+
# invoke other programs to do the real work, though it may do the
33+
# work itself too.
34+
#
35+
# Note that 'pre-revprop-change' must be executable by the user(s) who will
36+
# invoke it (typically the user httpd runs as), and that user must
37+
# have filesystem-level permission to access the repository.
38+
#
39+
# On a Windows system, you should name the hook program
40+
# 'pre-revprop-change.bat' or 'pre-revprop-change.exe',
41+
# but the basic idea is the same.
42+
#
43+
# The hook program typically does not inherit the environment of
44+
# its parent process. For example, a common problem is for the
45+
# PATH environment variable to not be set to its usual value, so
46+
# that subprograms fail to launch unless invoked via absolute path.
47+
# If you're having unexpected problems with a hook program, the
48+
# culprit may be unusual (or missing) environment variables.
49+
#
50+
# Here is an example hook script, for a Unix /bin/sh interpreter.
51+
# For more examples and pre-written hooks, see those in
52+
# the Subversion repository at
53+
# http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/ and
54+
# http://svn.collab.net/repos/svn/trunk/contrib/hook-scripts/
55+
56+
57+
REPOS="$1"
58+
REV="$2"
59+
USER="$3"
60+
PROPNAME="$4"
61+
ACTION="$5"
62+
63+
if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi
64+
if [ "$ACTION" = "M" -a "${PROPNAME%:*}" = "test" ]; then exit 0; fi
65+
if [ "$ACTION" = "A" -a "${PROPNAME%:*}" = "test" ]; then exit 0; fi
66+
67+
echo "
68+
Changing revision properties other than svn:log and test:* is prohibited.
69+
Got ACTION: $ACTION, PROPNAME: $PROPNAME
70+
" >&2
71+
72+
exit 1

0 commit comments

Comments
 (0)