We’ve been having some issues with people committing to the subversion server without entering a comment. Its easy to to require a comment using a “pre-commit” hook, which is a script that runs before someone’s changes are committed to the repository. A sample commit hook is supplied with subversion that you can enable to require comments. The problem is it doesn’t report back any error message (users will just get a generic “commit failed” in their svn client), and there is no provision for making sure the comment is a minimum length.

I tried to modify the example script, but I’m pretty bad with shell scripting. I looked for a perl one, which I knew I could easily modify, but couldn’t find any. So I whipped this one up:

#!/usr/bin/perl

# config section
$minchars = 4;
$svnlook = '/usr/bin/svnlook';

#--------------------------------------------
$repos = $ARGV[0];
$txn = $ARGV[1];
$comment = `$svnlook log -t "$txn" "$repos"`;
chomp($comment);

if ( length($comment) == 0 ) {
  print STDERR "A comment is required!";
  exit(1);
  }
elsif ( length($comment) < $minchars ) {
  print STDERR "Comment must be at least $minchars characters.";
  exit(1);
  }

exit(0);

Those error messages get sent back to the client and display just fine in TortoiseSVN or whatever you use.

My subversion server is running on Linux, but the script should run on Windows with little modification, if you have perl installed.

25 Comments

  1. Rob Wilkerson says:

    If anyone’s interested in simply modifying the built-in script, here’s what I’ve done:

    SVNLOOK=/usr/bin/svnlook
    LOGMSG=`$SVNLOOK log -t “$TXN” “$REPOS” | grep “[a-zA-Z0-9]” | wc -c`

    if [ “$LOGMSG” -lt 1 ]; then
    echo -e “Please provide a meaningful comment when committing changes.” 1>&2
    exit 1
    fi

    The “1>&2” operator redirects to the standard error rather than the standard output which is what allows the message to display in TortoiseSVN. I’ve never run Svn on a Windows box, so your mileage may vary. This works great on a Linux install to which I connect via TSVN, Subclipse and the command line.

    Hope this helps.

  2. patrick says:

    Where does this go?

  3. Ryan Stille says:

    Patrick, there is a “hooks” subdirectory under your repository directory. All your hook scripts go into there. By repository directory, I mean where your repository is actually stored on the machine that is running the subversion server.

  4. patrick says:

    Thanks so much for the quick reply. I must be doing something incorrectly; this is my pre-commit.tmpl in hooks/

    REPOS=”$1″
    TXN=”$2″

    # Make sure that the log message contains some text.
    SVNLOOK=/usr/bin/svnlook
    #$SVNLOOK log -t “$TXN” “$REPOS” | \
    # grep “[a-zA-Z0-9]” > /dev/null || exit 1

    LOGMSG=`$SVNLOOK log -t “$TXN” “$REPOS” | grep “[a-zA-Z0-9]” | wc -c`

    if [ “$LOGMSG” -lt 5 ]; then
    echo -e “Please provide a meaningful comment when committing changes.” 1>&2
    exit 1
    fi

    # Check that the author of this commit has the rights to perform
    # the commit on the files and directories being modified.
    commit-access-control.pl “$REPOS” “$TXN” commit-access-control.cfg || exit 1

    # All checks passed, so allow the commit.
    exit 0

    This seems to still let me put a single dot for the comment.

  5. Ryan Stille says:

    You need to rename it to pre-commit, without the “.tmpl” on it, and make sure its executable. I probably should have gotten into more detail in my post.

  6. patrick says:

    Thanks a lot. I used your perl script. Couldn’t get the bash script the other guy posted to work.

  7. Uzo says:

    Hi I am trying to write a hook script that will fail the commit if there is no bug id. I am getting frustrated with not being able to do this. I have no technical knowledge though and this is what I encountered. I use the tortoiseSVN client, I noticed that there is no svnlook in my bin directory. I copied it across manually and this script was written for me in python

    #!/usr/bin/python

    # commit acceptance python client for SVN

    import os

    import re

    import sys

    import urlparse

    # configure svnlook path

    svnlookPath = ‘\”C:\\Program Files\\VisualSVN Server\\bin\\svnlook.exe\”‘

    # get committer

    try:

    f = os.popen(svnlookPath + ‘ author -t ‘ + sys.argv[2] + ‘ ‘ + sys.argv[1])

    committer = f.read()

    if f.close():

    raise 1

    committer = committer.rstrip(“\n\r”)

    except:

    print >> sys.stderr, ‘Unable to get committer with svnlook.’

    print >> sys.stderr, svnlookPath

    print >> sys.stderr, sys.argv[1]

    print >> sys.stderr, sys.argv[2]

    sys.exit(1)

    # get commit message

    try:

    f = os.popen(svnlookPath + ‘ log -t ‘ + sys.argv[2] + ‘ ‘ + sys.argv[1])

    commitMessage = f.read()

    if f.close():

    raise 1

    commitMessage = commitMessage.rstrip(‘\n\r’)

    except:

    print >> sys.stderr, ‘Unable to get commit message with svnlook.’

    print >> sys.stderr, svnlookPath

    print >> sys.stderr, sys.argv[1]

    print >> sys.stderr, sys.argv[2]

    sys.exit(1)

    # print arguments

    # print >> sys.stderr, ‘Committer: ‘ + committer

    print >> sys.stderr, ‘Commit message: “‘ + commitMessage + ‘”‘

    if (re.match(‘^[a-zA-Z]+-[0-9]+([\s]+|$)’,commitMessage)):

    print >> sys.stderr, ‘Commit accepted.’

    sys.exit(0)

    else:

    print >> sys.stderr, ‘Commit rejected: This repository requires a commit message to begin with a Jira issue number.\n\reg JIRAPRJ-1’

    sys.exit(1)

    PLEASE HELP!!!

  8. Rob Wilkerson says:

    I’ve never installed Svn on Windows, but “#!” is a Unix script indicator. The paths you reference also appear Unix-centric. Are you sure you installed the Windows version of Svn server (assuming there is such a thing)? Changing the extension to .bat is meaningless if the syntax is that of a Unix shell script.

  9. Asim says:

    Hi Rob,
    Thanks for the quick update. I actually did download the Windows version and for some reason it has the same pre-hooks as unix then.

    I followed these steps to install it:
    http://blogs.vertigosoftware.com/teamsystem/archive/2006/01/16/Setting_up_a_Subversion_Server_under_Windows.aspx

    And its running fine as is, no pre-commits message checks though 🙁

  10. Asim says:

    Hi Guys,

    I’m new to SVN. Its my second day with SVN today and I’m trying to setup a pre-hook to force a properly formatted commit message. I have installed SVN on windows and renamed the pre-hook file to .bat but it throws these error messages.

    Does this mean that I need to install some sort of an environment there? Please help!!

    Thanks

    Error: Commit failed (details follow):
    Error: ‘pre-commit’ hook failed with error output:
    Error: ‘#!’ is not recognized as an internal or external command,
    Error: operable program or batch file.
    Error: ‘#’ is not recognized as an internal or external command,
    Error: operable program or batch file.
    [ long list of this snipped… ]
    Error: ‘REPOS’ is not recognized as an internal or external command,
    Error: operable program or batch file.
    Error: ‘TXN’ is not recognized as an internal or external command,
    Error: operable program or batch file.
    Error: ‘#’ is not recognized as an internal or external command,
    Error: operable program or batch file.
    Error: Unknown command: ‘=/usr/local/bin/svnlook’
    Error: Type ‘svnlook help’ for usage.
    Error: ‘$SVNLOOK’ is not recognized as an internal or external command,
    Error: operable program or batch file.

  11. Felix says:

    No Commit Without Comment 🙂

  12. Martin says:

    I can’t for the life of me get my hooks to print in stderr. Not through a bash script, not in python scripts. I managed to do a few errors in the python script which prompted the python interpreter to write those errors through stderr during a commit 😛 But other than that? It just won’t work.

    Any environmental things that need setting up or some such? hm

  13. Anonymous says:

    What would be a Windows equivalent of this script by editing the .tmpl?

  14. Dave Schinkel says:

    I assume this script would not work by pasting it and using it in a Windows environment.  So how would you do this in a Windows environment and add this same kind of hook?  Anyone, anyone?

  15. Ryan says:

    Dave you could install Perl for Windows and use this script.  You'll need to change a few things of course, the path to the svnlook program won't be the same for example.

    Or you could try a windows batch file.

  16. Dave Schinkel says:

    Nice, thank you!

  17. Dave Schinkel says:

    I was also told by a former collegue that you can just use the property tsvn:logminsize on your entire repository

  18. Dan Walker says:

    Nice, clean Perl script.  Thanks!

  19. Neil says:

    Thanks so much! Beautiful script

  20. Shah says:

    many thanks 🙂
    I am trying to included code reviewer test as well, but being newbie not able to write perl code 🙁

  21. shag says:

    can i able to force commands only for cpp files in svn

  22. sagar says:

    hello i m using webfaction hosting and i put that script as pre-commit.sh ..but its not executable ???..can u plz suggest me..??

  23. Keshav says:

    Hello all,
    I want to mandate a specific pattern(Should start with AS- ) in the commit message while I commit to SVN . Could someone help me in writing a script for this ?
    Any help on this would be greatly appreciated …

    Thanks,
    K

  24. Johnny C says:

    Thank you all. The STDERR thing is the tricky part that I was looking for.

  25. suma ramesh says:

    HI

    I want to include Pre commit script..

    I have renamed the file from pre-commit to pre-commit.html.

    REPOS=”$1″
    TXN=”$2″

    # Make sure that the log message contains some text.
    SVNLOOK=/usr/bin/svnlook
    $SVNLOOK log -t “$TXN” “$REPOS” | \
    grep “[a-zA-Z0-9]” > /dev/null || exit 1

    # Check that the author of this commit has the rights to perform
    # the commit on the files and directories being modified.
    commit-access-control.pl “$REPOS” “$TXN” commit-access-control.cfg || exit 1

    # All checks passed, so allow the commit.
    exit 0

    Kindly tell me what are the changes i need to do…