Search code examples
javasvnpre-commit-hookautodoc

Check if Java Class is commented in SVN Precommit hook


I want to ensure that a Java class is commented, before someone commits something into the SVN repository. So I want to realize the following workflow:

  1. User changes something in a class
  2. User wants to commit class
  3. Before executing the commit to the repository, SVN or something else checks if there are comments before the class and before public methods (for Java AutoDoc).
  4. If there are comments => Commit, Otherwise return Error message

How can I realize this? I found a lot about pre-commit hooks. But everything was about checking if the commit message/comment is set.

It would be very nice and helpful if someone could provide a solution for this problem.


Solution

  • Yes, you can do it, using CheckStyle.

    First, download the CheckStyle jar, and install it somewhere. Then, create a new xml config file for CheckStyle to check if your public methods/classes have some JavaDoc (you can call it javadoc_check.xml for instance):

    <?xml version="1.0"?>
    <!DOCTYPE module PUBLIC
              "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
                        "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
    
    <module name="Checker">
        <module name="TreeWalker">
            <module name="JavadocMethod">
                <property name="scope" value="public"/>
            </module>
            <module name="JavadocType">
                <property name="scope" value="public"/>
            </module>
        </module>
    </module>
    

    Once it's done, you can create you pre_commit hook, like that:

    #!/bin/bash
    
    REPOS="$1"
    TXN="$2"
    
    CHECKSTYLEJAR=/path/to/checkstyle-5.7/checkstyle-5.7-all.jar
    CHECKSTYLECONFIG=/path/to/javadoc_check.xml
    
    SVNLOOK=/usr/bin/svnlook
    JAVA=/usr/bin/java
    
    EXITSTATUS=0
    ERRORMARKER=__ERROR_MARKER__
    
    # Create temporary dir
    TMPDIR=$(mktemp -d)
    
    # Iterate on the files commited
    while read changeline;
    do
        # Get the filename
        file=${changeline:4}
    
        # Check if it's an Updated or Added java file
        if [[ $file == *.java && ($changeline == U* || $changeline == A*) ]] ; then
            # Get the file content in a temporary file
            $SVNLOOK cat -t "$TXN" "$REPOS" "$file" > $TMPDIR/${file##*/}
    
            echo -e "\n=> Checking $file"
            # Check the file with checkstyle
            ( $JAVA -jar $CHECKSTYLEJAR -c $CHECKSTYLECONFIG $TMPDIR/${file##*/} 2>&1 || echo "$ERRORMARKER" 1>&2 ) | sed -e "s{$TMPDIR/{{"
    
            # Delete the temporary file
            rm $TMPDIR/${file##*/}
        fi
    done < <($SVNLOOK changed -t "$TXN" "$REPOS") 3>&2 2>&1 1>&3 | grep "$ERRORMARKER" && EXITSTATUS=1 # Check for errors
    
    # Delete temporary dir
    rmdir $TMPDIR
    
    exit $EXITSTATUS
    

    Don't forget to change the path to the CheckStyle jar and CheckStyle config.

    The next time you will try to commit a java file without JavaDoc comment on a public method/class, the commit will be cancelled, and you will have an error message:

    $ svn commit
    Sending        test.java
    Transmitting file data .svn: E165001: Commit failed (details follow):
    svn: E165001: Commit blocked by pre-commit hook (exit code 1) with output:
    
    => Checking test.java
    Starting audit...
    test.java:9:1: Missing a Javadoc comment.
    Audit done.
    
    svn: E165001: Your commit message was left in a temporary file:
    svn: E165001:    '/path/to/project/svn-commit.1.tmp'
    $
    

    If you commit more than one file, all the files will be checked, and the commit will be authorized only if all the modified/added java files have JavaDoc comments.