[sysadmin-bin] Add a pre-receive hook that limits the translations user
- From: Andrea Veri <av src gnome org>
- To: gnome-sysadmin gnome org,commits-list gnome org
- Subject: [sysadmin-bin] Add a pre-receive hook that limits the translations user
- Date: Sat, 24 Aug 2013 12:40:07 +0000 (UTC)
commit 3548bd217bb063cd6d5ed066a2934c36447bc83c
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Tue Aug 6 11:12:50 2013 -0400
Add a pre-receive hook that limits the translations user
Before we allow the 'translations' user to commit, check that the
change is something expect l10n.gnome.org - a change to a .po file,
a LINGUAS file, or the addition of a language to a help Makefile.am.
https://bugzilla.gnome.org/show_bug.cgi?id=599066
Signed-off-by: Andrea Veri <av gnome org>
git/gnome-pre-receive | 8 +++
git/pre-receive-check-translations | 117 ++++++++++++++++++++++++++++++++++++
2 files changed, 125 insertions(+), 0 deletions(-)
---
diff --git a/git/gnome-pre-receive b/git/gnome-pre-receive
index a5ed9fb..296021f 100755
--- a/git/gnome-pre-receive
+++ b/git/gnome-pre-receive
@@ -63,12 +63,20 @@ EOF
exit 1
fi
+my_uid=`id -u`
+translations_uid=`id -u translations`
+[ $? == 0 ] || exit 1
+
while read oldrev newrev refname; do
# Unlike the gnome-post-receive script, where we play fancy games
# with 'tee', we invoke the different pre-receive hooks separately
# for each ref that is updated. This keeps things simple and
# reliable and none of the scripts need all the refs at once.
+ # First (and written in Python) since we're trying to make it hard
+ # to bypass if l10.gnome.org were compromised.
+ [ $my_uid != $translations_uid ] || $BINDIR/pre-receive-check-translations $oldrev $newrev $refname ||
exit 1
+
$BINDIR/pre-receive-check-policy $oldrev $newrev $refname || exit 1
$BINDIR/pre-receive-check-maintainers $oldrev $newrev $refname || exit 1
$BINDIR/pre-receive-check-po $oldrev $newrev $refname || exit 1
diff --git a/git/pre-receive-check-translations b/git/pre-receive-check-translations
new file mode 100755
index 0000000..7300f29
--- /dev/null
+++ b/git/pre-receive-check-translations
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+
+# This checks to see if an update is an update that the automated
+# translations user is allowed to do. This user is used by l10n.gnome.org.
+#
+# The per-repository git config keys
+#
+# hooks.po-directories (default 'po')
+# hooks.help-directories (default 'help')
+#
+# Define the directories that have po-file or translated help structure.
+
+import re
+import os
+import sys
+from git import *
+
+def error(msg):
+ print >>sys.stderr, msg
+ sys.exit(1)
+
+def config_dirs(key, default):
+ try:
+ raw = git.config("key", _quiet=True)
+ except CalledProcessError:
+ raw = default
+
+ return [os.path.normpath(p) for p in raw.split()]
+
+def relative_path(path, base):
+ if path.startswith(base + '/'):
+ return path[len(base) + 1:]
+ else:
+ return None
+
+def check_translations(oldrev, newrev, refname):
+ if not refname.startswith('refs/heads/'):
+ error("translations user can only update branches")
+
+ if re.match(r'^0+$', oldrev):
+ error("translations user cannot create branches")
+
+ if re.match(r'^0+$', newrev):
+ error("translations user cannot delete branches")
+
+ po_directories = config_dirs('hooks.po-directories', 'po')
+ help_directories = config_dirs('hooks.help-directories', 'help')
+
+ # Iterate through all changed files. Passing -z to git diff-tree
+ # gives a result with separation by NUL characters, avoiding
+ # having to deal with quoting. NUL separates the meta-information
+ # from the pathname and from the next entry
+ lines = git.diff_tree(oldrev, newrev, z=True, r=True).split('\0')
+ for i in xrange(0, len(lines) - 1, 2):
+ srcmode, destmode, srcsha, destsha, status = lines[i].split()
+ path = lines[i + 1]
+
+ ok = False
+ for dir in po_directories:
+ relpath = relative_path(path, dir)
+ if relpath is None:
+ continue
+
+ # Arbitrary change to a .po file
+ if re.match(r'^[a-zA-Z _]+ po$', relpath):
+ ok = True
+
+ # Arbitrary change to LINGUAS
+ if relpath == 'LINGUAS':
+ ok = True
+
+ for dir in help_directories:
+ relpath = relative_path(path, dir)
+ if relpath is None:
+ continue
+
+ # Arbitrary change to a .po file in a language subdir
+ if re.match(r'^[a-zA-Z _]+/[a-zA-Z _]+ po$', relpath):
+ ok = True
+ # Arbitrary change to a PNG in the figures/ directory
+ elif re.match(r'^[a-zA-Z _]+/figures/[a-zA-Z0-9_-].png$', relpath):
+ ok = True
+ # Very limited changes to <help-dir>/Makefile.am
+ elif relpath == 'Makefile.am':
+ if status != 'M':
+ error("translations user cannot modify '%s' in this way" % path)
+
+ diff = git.diff(oldrev + ':' + path, newrev + ':' + path).split('\n')
+
+ in_header = True
+ for line in diff:
+ # Ignore anything up to the first @@
+ if line.startswith('@@'):
+ in_header = False
+ if in_header:
+ continue
+
+ # Changes in a diff are line that begin with a '+' or '-' character
+ if not re.match(r'^[-+]', line):
+ continue
+
+ # The only changes that we allow are changes that add or delete a
+ # DOC_LINGUAS line we understand and validate against a strict
+ # pattern. All other changes are forbidden.
+ if not re.match(r'^[-+]DOC_LINGUAS *= *([a-zA-Z _]+( +|$))*$', line):
+ error("translations user cannot modify '%s' in this way" % path)
+
+ ok = True
+
+ if not ok:
+ error("translations user cannot modify '%s'" % path)
+
+if len(sys.argv) == 4:
+ check_translations(*sys.argv[1:])
+else:
+ for line in sys.stdin:
+ check_translations(line.split())
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]