summaryrefslogtreecommitdiff
path: root/tools/hook-scripts/validate-extensions.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/hook-scripts/validate-extensions.py')
-rwxr-xr-xtools/hook-scripts/validate-extensions.py110
1 files changed, 110 insertions, 0 deletions
diff --git a/tools/hook-scripts/validate-extensions.py b/tools/hook-scripts/validate-extensions.py
new file mode 100755
index 0000000..ed0283d
--- /dev/null
+++ b/tools/hook-scripts/validate-extensions.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#
+
+"""\
+Check that any files pending commit into a Subversion repository have
+suitable file extensions, printing an error and exiting with an
+errorful value if any files fail validation. This is intended to be
+used as a Subversion pre-commit hook script.
+
+Syntax 1:
+
+ validate-extensions.py REPOS_PATH TXN_NAME deny EXT [...]
+
+ Ensure that any newly added files do *not* have one of the provided
+ file extensions.
+
+
+Syntax 2:
+
+ validate-extensions.py REPOS_PATH TXN_NAME allow EXT [...]
+
+ Ensure that any newly added files *do* have one of the provided
+ file extensions. (Extension-less files are disallowed.)
+
+"""
+
+import sys
+import os
+from svn import repos, fs, core
+
+def validate_added_extensions(repos_path, txn_name, extensions, action):
+ # Open the repository and transaction.
+ fs_ptr = repos.fs(repos.open(repos_path))
+ txn_t = fs.open_txn(fs_ptr, txn_name)
+ txn_root = fs.txn_root(txn_t)
+
+ # Fetch the changes made in this transaction.
+ changes = fs.svn_fs_paths_changed(txn_root)
+ paths = changes.keys()
+
+ # Check the changes.
+ for path in paths:
+ change = changes[path]
+
+ # Always allow deletions.
+ if change.change_kind == fs.path_change_delete:
+ continue
+
+ # Always allow non-files.
+ kind = fs.check_path(txn_root, path)
+ if kind != core.svn_node_file:
+ continue
+
+ # If this was a newly added (without history) file ...
+ if ((change.change_kind == fs.path_change_replace) \
+ or (change.change_kind == fs.path_change_add)):
+ copyfrom_rev, copyfrom_path = fs.copied_from(txn_root, path)
+ if copyfrom_rev == core.SVN_INVALID_REVNUM:
+
+ # ... then check it for a valid extension.
+ base, ext = os.path.splitext(path)
+ if ext:
+ ext = ext[1:].lower()
+ if ((ext in extensions) and (action == 'deny')) \
+ or ((ext not in extensions) and (action == 'allow')):
+ sys.stderr.write("Path '%s' has an extension disallowed by server "
+ "configuration.\n" % (path))
+ sys.exit(1)
+
+def usage_and_exit(errmsg=None):
+ stream = errmsg and sys.stderr or sys.stdout
+ stream.write(__doc__)
+ if errmsg:
+ stream.write("ERROR: " + errmsg + "\n")
+ sys.exit(errmsg and 1 or 0)
+
+def main():
+ argc = len(sys.argv)
+ if argc < 5:
+ usage_and_exit("Not enough arguments.")
+ repos_path = sys.argv[1]
+ txn_name = sys.argv[2]
+ action = sys.argv[3]
+ if action not in ("allow", "deny"):
+ usage_and_exit("Invalid action '%s'. Expected either 'allow' or 'deny'."
+ % (action))
+ extensions = [x.lower() for x in sys.argv[4:]]
+ validate_added_extensions(repos_path, txn_name, extensions, action)
+
+if __name__ == "__main__":
+ main()