1 | #!/bin/bash |
---|
2 | #------------------------------------------------------------------------------- |
---|
3 | # Copyright (C) 2006-2021 British Crown (Met Office) & Contributors. |
---|
4 | # |
---|
5 | # This file is part of FCM, tools for managing and building source code. |
---|
6 | # |
---|
7 | # FCM is free software: you can redistribute it and/or modify |
---|
8 | # it under the terms of the GNU General Public License as published by |
---|
9 | # the Free Software Foundation, either version 3 of the License, or |
---|
10 | # (at your option) any later version. |
---|
11 | # |
---|
12 | # FCM is distributed in the hope that it will be useful, |
---|
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
15 | # GNU General Public License for more details. |
---|
16 | # |
---|
17 | # You should have received a copy of the GNU General Public License |
---|
18 | # along with FCM. If not, see <http://www.gnu.org/licenses/>. |
---|
19 | #------------------------------------------------------------------------------- |
---|
20 | # NAME |
---|
21 | # pre-commit |
---|
22 | # |
---|
23 | # SYNOPSIS |
---|
24 | # pre-commit REPOS TXN |
---|
25 | # |
---|
26 | # ARGUMENTS |
---|
27 | # REPOS - the path to the Subversion repository |
---|
28 | # TXN - the commit transaction |
---|
29 | # |
---|
30 | # DESCRIPTION |
---|
31 | # This script performs pre-commit check, including: |
---|
32 | # 1. Path-based permission check using "svnperms.py", if |
---|
33 | # "$REPOS/hooks/svnperms.conf" exists. |
---|
34 | # 2. Size check. Transaction should occupy less than 10MB, or the number of |
---|
35 | # MB specified in "$REPOS/hooks/pre-commit-size-threshold.conf". |
---|
36 | # 3. Runs "$REPOS/hooks/pre-commit-custom" if it exists. |
---|
37 | # |
---|
38 | # ENVIRONMENT VARIABLES |
---|
39 | # FCM_SVN_HOOK_ADMIN_EMAIL |
---|
40 | # The name of the admin team. (Default is "Admin".) |
---|
41 | #------------------------------------------------------------------------------- |
---|
42 | set -eu |
---|
43 | |
---|
44 | REPOS=$1 |
---|
45 | TXN=$2 |
---|
46 | |
---|
47 | export PATH=${PATH:-'/usr/local/bin:/bin:/usr/bin'}:$(dirname $0) |
---|
48 | THIS=$(basename $0) |
---|
49 | USER=${USER:-$(whoami)} |
---|
50 | NAME=$(basename "$REPOS") |
---|
51 | LOG_TXN="$REPOS/log/$THIS-$TXN.log" |
---|
52 | |
---|
53 | begin() { |
---|
54 | local NOW=$(date -u +%FT%H:%M:%SZ) |
---|
55 | local AUTHOR=$(svnlook author -t "$TXN" "$REPOS") |
---|
56 | echo "$NOW+ $TXN by $AUTHOR" |
---|
57 | svnlook changed -t "$TXN" "$REPOS" |
---|
58 | } |
---|
59 | |
---|
60 | main() { |
---|
61 | local ADMIN_EMAIL=${FCM_SVN_HOOK_ADMIN_EMAIL:-Admin} |
---|
62 | |
---|
63 | # Check size. |
---|
64 | local MB=1048576 |
---|
65 | local THRESHOLD=10 |
---|
66 | local SIZE_THRESHOLD_FILE="$REPOS/hooks/$THIS-size-threshold.conf" |
---|
67 | if [[ -f "$SIZE_THRESHOLD_FILE" && -r "$SIZE_THRESHOLD_FILE" ]]; then |
---|
68 | THRESHOLD=$(<"$SIZE_THRESHOLD_FILE") |
---|
69 | fi |
---|
70 | local TXN_FILE="$REPOS/db/txn-protorevs/$TXN.rev" |
---|
71 | local SIZE=$(du -b "$TXN_FILE" | cut -f 1) |
---|
72 | if ((SIZE > THRESHOLD * MB)); then |
---|
73 | SIZE=$(du -h "$TXN_FILE" | cut -f 1) |
---|
74 | echo "$NAME@$TXN: changeset size ${SIZE}B exceeds ${THRESHOLD}MB." >&2 |
---|
75 | echo "Email $ADMIN_EMAIL if you need to bypass this restriction." >&2 |
---|
76 | return 1 |
---|
77 | elif ((SIZE > MB)); then |
---|
78 | # Log any changesets bigger than 1MB |
---|
79 | SIZE=$(du -h "$TXN_FILE" | cut -f 1) |
---|
80 | echo "$NAME@$TXN: changeset size ${SIZE}B exceeds 1MB." >&2 |
---|
81 | fi |
---|
82 | |
---|
83 | # Check permission. |
---|
84 | local PERM_CONFIG="$REPOS/hooks/svnperms.conf" |
---|
85 | if [[ -r "$PERM_CONFIG" && -s "$PERM_CONFIG" ]]; then |
---|
86 | svnperms.py -r "$REPOS" -t "$TXN" -f "$PERM_CONFIG" || return $? |
---|
87 | elif [[ -L "$PERM_CONFIG" ]]; then |
---|
88 | echo "$NAME: permission configuration file not found." >&2 |
---|
89 | echo "$ADMIN_EMAIL has been notified." >&2 |
---|
90 | return 1 |
---|
91 | fi |
---|
92 | |
---|
93 | # Verify owner of any new branches, if relevant |
---|
94 | local COMMIT_CONFIG="${REPOS}/hooks/commit.conf" |
---|
95 | if grep -q 'verify-branch-owner' "$COMMIT_CONFIG" 2>/dev/null; then |
---|
96 | pre-commit-verify-branch-owner "$REPOS" "$TXN" || return $? |
---|
97 | fi |
---|
98 | |
---|
99 | # Custom checking, if required |
---|
100 | local CUSTOM_HOOK="$REPOS/hooks/$THIS-custom" |
---|
101 | if [[ -x "$CUSTOM_HOOK" ]]; then |
---|
102 | "$CUSTOM_HOOK" "$REPOS" "$TXN" || return $? |
---|
103 | fi |
---|
104 | } |
---|
105 | |
---|
106 | RET_CODE=0 |
---|
107 | begin 1>"${LOG_TXN}" 2>&1 |
---|
108 | LOG_TXN_SIZE="$(stat -c '%s' "${LOG_TXN}")" |
---|
109 | if ! main 1>>"${LOG_TXN}" 2>&1; then |
---|
110 | if [[ -n ${FCM_SVN_HOOK_ADMIN_EMAIL:-} ]]; then |
---|
111 | FROM= |
---|
112 | if [[ -n ${FCM_SVN_HOOK_NOTIFICATION_FROM:-} ]]; then |
---|
113 | FROM="-r${FCM_SVN_HOOK_NOTIFICATION_FROM:-}" |
---|
114 | fi |
---|
115 | mail "$FROM" -s "[$THIS] $REPOS@$TXN" \ |
---|
116 | "$FCM_SVN_HOOK_ADMIN_EMAIL" <"$LOG_TXN" || true |
---|
117 | fi |
---|
118 | cat "$LOG_TXN" |
---|
119 | cat "$LOG_TXN" >&2 |
---|
120 | RET_CODE=1 |
---|
121 | elif [[ "${LOG_TXN_SIZE}" != "$(stat -c '%s' "${LOG_TXN}")" ]]; then |
---|
122 | cat "$LOG_TXN" |
---|
123 | fi |
---|
124 | rm -f "$LOG_TXN" |
---|
125 | exit $RET_CODE |
---|