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
|
#!/bin/bash
#-------------------------------------------------------------------------------
# Copyright (C) 2006-2021 British Crown (Met Office) & Contributors.
#
# This file is part of FCM, tools for managing and building source code.
#
# FCM is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# FCM is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with FCM. If not, see <http://www.gnu.org/licenses/>.
#-------------------------------------------------------------------------------
# NAME
# pre-commit
#
# SYNOPSIS
# pre-commit REPOS TXN
#
# ARGUMENTS
# REPOS - the path to the Subversion repository
# TXN - the commit transaction
#
# DESCRIPTION
# This script performs pre-commit check, including:
# 1. Path-based permission check using "svnperms.py", if
# "$REPOS/hooks/svnperms.conf" exists.
# 2. Size check. Transaction should occupy less than 10MB, or the number of
# MB specified in "$REPOS/hooks/pre-commit-size-threshold.conf".
# 3. Runs "$REPOS/hooks/pre-commit-custom" if it exists.
#
# ENVIRONMENT VARIABLES
# FCM_SVN_HOOK_ADMIN_EMAIL
# The name of the admin team. (Default is "Admin".)
#-------------------------------------------------------------------------------
set -eu
REPOS=$1
TXN=$2
export PATH=${PATH:-'/usr/local/bin:/bin:/usr/bin'}:$(dirname $0)
THIS=$(basename $0)
USER=${USER:-$(whoami)}
NAME=$(basename "$REPOS")
LOG_TXN="$REPOS/log/$THIS-$TXN.log"
begin() {
local NOW=$(date -u +%FT%H:%M:%SZ)
local AUTHOR=$(svnlook author -t "$TXN" "$REPOS")
echo "$NOW+ $TXN by $AUTHOR"
svnlook changed -t "$TXN" "$REPOS"
}
main() {
local ADMIN_EMAIL=${FCM_SVN_HOOK_ADMIN_EMAIL:-Admin}
# Check size.
local MB=1048576
local THRESHOLD=10
local SIZE_THRESHOLD_FILE="$REPOS/hooks/$THIS-size-threshold.conf"
if [[ -f "$SIZE_THRESHOLD_FILE" && -r "$SIZE_THRESHOLD_FILE" ]]; then
THRESHOLD=$(<"$SIZE_THRESHOLD_FILE")
fi
local TXN_FILE="$REPOS/db/txn-protorevs/$TXN.rev"
local SIZE=$(du -b "$TXN_FILE" | cut -f 1)
if ((SIZE > THRESHOLD * MB)); then
SIZE=$(du -h "$TXN_FILE" | cut -f 1)
echo "$NAME@$TXN: changeset size ${SIZE}B exceeds ${THRESHOLD}MB." >&2
echo "Email $ADMIN_EMAIL if you need to bypass this restriction." >&2
return 1
elif ((SIZE > MB)); then
# Log any changesets bigger than 1MB
SIZE=$(du -h "$TXN_FILE" | cut -f 1)
echo "$NAME@$TXN: changeset size ${SIZE}B exceeds 1MB." >&2
fi
# Check permission.
local PERM_CONFIG="$REPOS/hooks/svnperms.conf"
if [[ -r "$PERM_CONFIG" && -s "$PERM_CONFIG" ]]; then
svnperms.py -r "$REPOS" -t "$TXN" -f "$PERM_CONFIG" || return $?
elif [[ -L "$PERM_CONFIG" ]]; then
echo "$NAME: permission configuration file not found." >&2
echo "$ADMIN_EMAIL has been notified." >&2
return 1
fi
# Verify owner of any new branches, if relevant
local COMMIT_CONFIG="${REPOS}/hooks/commit.conf"
if grep -q 'verify-branch-owner' "$COMMIT_CONFIG" 2>/dev/null; then
pre-commit-verify-branch-owner "$REPOS" "$TXN" || return $?
fi
# Custom checking, if required
local CUSTOM_HOOK="$REPOS/hooks/$THIS-custom"
if [[ -x "$CUSTOM_HOOK" ]]; then
"$CUSTOM_HOOK" "$REPOS" "$TXN" || return $?
fi
}
RET_CODE=0
begin 1>"${LOG_TXN}" 2>&1
LOG_TXN_SIZE="$(stat -c '%s' "${LOG_TXN}")"
if ! main 1>>"${LOG_TXN}" 2>&1; then
if [[ -n ${FCM_SVN_HOOK_ADMIN_EMAIL:-} ]]; then
mail -s "[$THIS] $REPOS@$TXN" "$FCM_SVN_HOOK_ADMIN_EMAIL" <"$LOG_TXN" \
|| true
fi
cat "$LOG_TXN"
cat "$LOG_TXN" >&2
RET_CODE=1
elif [[ "${LOG_TXN_SIZE}" != "$(stat -c '%s' "${LOG_TXN}")" ]]; then
cat "$LOG_TXN"
fi
rm -f "$LOG_TXN"
exit $RET_CODE
|