Skip to content

Instantly share code, notes, and snippets.

@agarciadom
Created March 17, 2014 20:10
Show Gist options
  • Save agarciadom/9607256 to your computer and use it in GitHub Desktop.
Save agarciadom/9607256 to your computer and use it in GitHub Desktop.
SVN hook that checks that the message mentions an open ticket in a PostgreSQL-backed Redmine installation.
#!/bin/bash
# SVN hook that checks that the message mentions an open ticket in a PostgreSQL-backed Redmine installation.
# Copyright (C) 2014 Antonio García Domínguez
# Licensed under the GPLv3.
## CONFIGURATION
SVNLOOK=/usr/bin/svnlook
PSQL=/usr/bin/psql
PERL=/usr/bin/perl
DBHOST=localhost
DBNAME=redmine
DBUSER=redmine
# The key is stored in ~/.pgpass, not here.
## ARGUMENTS
if [[ "$#" != 2 ]]; then
echo "Usage: $0 repo_path tx_id" >&2
exit 200
fi
REPO_PATH="$1"
TX_ID="$2"
## FUNCTIONS
commit_message() {
# Dumps to stdout the message for this commit.
"$SVNLOOK" log "$REPO_PATH" -t "$TX_ID"
}
get_issue_id() {
# Tries to find an issue ID in the first line of stdin.
"$PERL" -e '$line = <>; $line =~ /(?:refs|references|IssueID|closes|fixes|cierra|arregla)\s*#([0-9]+)/i && print $1;'
}
check_if_open() {
# Usage: check_if_open issue_id
# Preconditions: issue_id is an integer.
# Postconditions: zero status if issue_id is an open Redmine issue, non-zero otherwise.
# Use a read-only transaction to improve security.
cat <<EOF |
PREPARE check_if_open (int) AS
SELECT COUNT(*) AS result
FROM issues i JOIN issue_statuses s ON s.id = i.status_id
WHERE s.is_closed AND i.id = \$1;
BEGIN READ ONLY;
EXECUTE check_if_open($1);
EOF
"$PSQL" -h "$DBHOST" "$DBNAME" "$DBUSER" -qt |
"$PERL" -e '$line = <>; $line =~ /([0-9]+)/; exit 1 if 1 != $1;'
}
## MAIN PROGRAM
COMMIT_MSG=$(commit_message)
if [[ -z "$COMMIT_MSG" ]]; then
# No message
echo "The commit message must not be empty." >&2
exit 1
fi
ISSUE_ID=$(echo "$COMMIT_MSG" | get_issue_id)
if [[ -z "$ISSUE_ID" ]]; then
echo "The commit message does not mention any ticket on its first line." >&2
echo "It should have something like 'refs #N', 'closes #N' or 'fixes #N'." >&2
exit 2
elif ! check_if_open "$ISSUE_ID"; then
echo "The ticket '$ISSUE_ID' does not exist or is not open." >&2
exit 3
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment