Server IP : 85.214.239.14 / Your IP : 18.118.10.37 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /proc/3/root/usr/share/subversion/hook-scripts/ |
Upload File : |
#!/usr/bin/python3 # # 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. # """Subversion pre-commit hook script that runs user configured commands to validate files in the commit and reject the commit if the commands exit with a non-zero exit code. The script expects a validate-files.conf file placed in the conf dir under the repo the commit is for. Note: As changed file paths $FILE are always represented as a Unicode (Py3) or UTF-8 (Py2) strings, you might need to set apropriate locale and PYTHONIOENCODING environment variable for this script and commands to handle non-ascii path and command outputs, especially you want to use svnlook cat command to inspect file contents.""" import sys import os import subprocess import fnmatch # Deal with the rename of ConfigParser to configparser in Python3 try: # Python >= 3.0 import configparser ConfigParser = configparser.ConfigParser except ImportError: # Python < 3.0 import ConfigParser as configparser ConfigParser = configparser.SafeConfigParser class Config(ConfigParser): """Superclass of SafeConfigParser with some customizations for this script""" def optionxform(self, option): """Redefine optionxform so option names are case sensitive""" return option def getlist(self, section, option): """Returns value of option as a list using whitespace to split entries""" value = self.get(section, option) if value: return value.split() else: return None def get_matching_rules(self, repo): """Return list of unique rules names that apply to a given repo""" rules = {} for option in self.options('repositories'): if fnmatch.fnmatch(repo, option): for rule in self.getlist('repositories', option): rules[rule] = True return rules.keys() def get_rule_section_name(self, rule): """Given a rule name provide the section name it is defined in.""" return 'rule:%s' % (rule) class Commands: """Class to handle logic of running commands""" def __init__(self, config): self.config = config def svnlook_changed(self, repo, txn): """Provide list of files changed in txn of repo""" svnlook = self.config.get('DEFAULT', 'svnlook') cmd = "'%s' changed -t '%s' '%s'" % (svnlook, txn, repo) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) changed = [] while True: line = p.stdout.readline() if not line: break line = line.strip() text_mod = line[0:1] # Only if the contents of the file changed (by addition or update) # directories always end in / in the svnlook changed output if line[-1:] != b"/" and (text_mod == b"A" or text_mod == b"U"): changed_path = line[4:] if not isinstance(changed_path, str): # svnlook always uses UTF-8 for internal path changed_path = changed_path.decode('utf-8') changed.append(changed_path) # wait on the command to finish so we can get the # returncode/stderr output data = p.communicate() if p.returncode != 0: err_mesg = data[1] if sys.stderr.encoding: err_mesg =err_mesg.decode(sys.stderr.encoding, 'backslashreplace') sys.stderr.write(err_mesg) sys.exit(2) return changed def user_command(self, section, repo, txn, fn): """ Run the command defined for a given section. Replaces $REPO, $TXN and $FILE with the repo, txn and fn arguments in the defined command. Returns a tuple of the exit code and the stderr output of the command""" cmd = self.config.get(section, 'command') cmd_env = os.environ.copy() cmd_env['REPO'] = repo cmd_env['TXN'] = txn cmd_env['FILE'] = fn p = subprocess.Popen(cmd, shell=True, env=cmd_env, stderr=subprocess.PIPE) data = p.communicate() err_mesg = data[1] if sys.stderr.encoding: err_mesg = err_mesg.decode(sys.stderr.encoding, 'backslashreplace') return (p.returncode, err_mesg) def main(repo, txn): exitcode = 0 config = Config() config.read(os.path.join(repo, 'conf', 'validate-files.conf')) commands = Commands(config) rules = config.get_matching_rules(repo) # no matching rules so nothing to do if len(rules) == 0: sys.exit(0) changed = commands.svnlook_changed(repo, txn) # this shouldn't ever happen if len(changed) == 0: sys.exit(0) for rule in rules: section = config.get_rule_section_name(rule) pattern = config.get(section, 'pattern') # skip leading slashes if present in the pattern if pattern[0] == '/': pattern = pattern[1:] for fn in fnmatch.filter(changed, pattern): (returncode, err_mesg) = commands.user_command(section, repo, txn, fn) if returncode != 0: sys.stderr.write( "\nError validating file '%s' with rule '%s' " \ "(exit code %d):\n" % (fn, rule, returncode)) sys.stderr.write(err_mesg) exitcode = 1 return exitcode if __name__ == "__main__": if len(sys.argv) != 3: sys.stderr.write("invalid args\n") sys.exit(0) try: sys.exit(main(sys.argv[1], sys.argv[2])) except configparser.Error as e: sys.stderr.write("Error with the validate-files.conf: %s\n" % e) sys.exit(2)