简体   繁体   中英

SVN pre-commit hook logic

I'm adding a logic in my svn pre-commit hook to check if there is QA(in upper case starting with space) in commit message then commit should fail. But its not working. Kindly assist me how to write it properly.

REPOS="$1"
TXN="$2"

# Make sure that the log message contains some text.
SVNLOOK=/usr/bin/svnlook

LOGMSG=$($SVNLOOK log -t "$TXN" "$REPOS")

# check if any comment has supplied by the commiter
if [ -z "$LOGMSG" ]; then
echo "Your commit was blocked because it have no comments." 1>&2
exit 1
fi

#check minimum size of text
if [ ${#LOGMSG} -lt 15 ]; then
echo "Your Commit was blocked because the comments does not meet minimum length requirements (15 letters)." 1>&2
exit 1
fi

# get TaskID by regex
TaskID=$(expr "$LOGMSG" : '\([#][0-9]\{1,9\}[:][" "]\)[A-Za-z0-9]*')

# Check if task id was found. 
if [ -z "$TaskID" ]; then

echo ""  1>&2
echo "No Task id found in log message \"$LOGMSG\"" 1>&2
echo ""  1>&2
echo "The TaskID must be the first item on the first line of the log message."  1>&2
echo ""  1>&2
echo "Proper TaskID format--> #123- 'Your commit message'  " 1>&2
exit 1
fi

#Check that QA should not be present in log message.

QA=$(expr "$LOGMSG" : '\(*[" "][QA][" "]\)')
if [ "$QA" == "QA" ]; then
echo ""  1>&2
echo "Your log message \"$LOGMSG\" must not contain QA in upper case." 1>&2
echo ""  1>&2
exit 1
fi

The regex is incorrect:

  • \\( starts a capturing group in expr , but you don't need a capturing group for your task
  • When * follows a \\( in a pattern, it tries to match a literal *
  • [QA] matches a single character, which can be Q or A
  • The pattern of expr must match from the start of the string

As it is, the regex doesn't correspond to your requirement.

Even if the above points are fixed, a pattern QA , "QA" with spaces around it, will not match commit messages like this:

  • "Fix the build of QA"
  • "Broken in QA, temporarily"
  • ... and so on...

That is, instead of "QA" with spaces around, you probably want to match QA with word boundaries around. This is easy to do using grep -w QA .

As you clarified in a comment, you really want a space before the "Q". In that case the -w flag of grep is not suitable, because that requires a word boundary at both sides of patterns. There is another way to match word boundaries, using \\< for word start and \\> for word end. So to have a space in front of "Q", and a word boundary after "A", you can write QA\\> , like this:

if grep -q ' QA\>' <<< "$LOGMSG"; then
    echo
    echo "Your log message \"$LOGMSG\" must not contain QA in upper case."
    echo
    exit 1
fi 1>&2

Notice some other improvements:

  • Instead of redirecting to stderr every single echo , you can redirect the entire if statement
  • Instead of echo "" you can write simply echo
  • Instead of storing the result of a command in a temporary variable, you can write conditionals on the exit code of commands

This could be an error with your regex expression checking for " QA ".

I find using this site pretty useful for testing out regex expressions - RegExr .

I put your (*[" "][QA][" "]) expression into the site and when I looked at the details of it (a tab link towards the bottom of the page), it would break down exactly what you regular expression would match with. From this, it was saying that it was looking for the following:

  1. 0 or more (
  2. Either a " or a space
  3. Either Q or A (not both)
  4. Either a " or a space
  5. Ending with a )

I put the following expression into it - ( (QA) ) and it was able to find the match in a sample svn message (TEST-117 QA testing message).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM