Search code examples
phpsvnmantispost-commit-hook

Why do I get this error: post-commit hook failed (exit code 255) with no output


I am getting the following error when I commit to a repository:

post-commit hook failed (exit code 255) with no output.

The post commit code is as follows:

@echo off

setlocal enableextensions

set REPOS=%1
set REV=%2
set TEMPFILE=C:\TEMP\%REV%.txt
set LOGFILE=D:\svn\logs\mysite\post_commit.log

set MANTIS_PATH="D:\home\mantis"

"C:\Program Files\SlikSvn\bin\svnlook" author %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" date %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" changed %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt
echo revision:[%REV%] >> %TEMPFILE% 2>>C:\TEMP\err.txt
"C:\Program Files\SlikSvn\bin\svnlook" log %REPOS% -r %REV% >> %TEMPFILE% 2>>C:\TEMP\err.txt

date /T >> %LOGFILE% 2>>C:\TEMP\err.txt
time /T >> %LOGFILE% 2>>C:\TEMP\err.txt
D:\wamp\bin\php\php5.3.0\php.exe %MANTIS_PATH%\scripts\checkin.php < %TEMPFILE% >> %LOGFILE% 2>>C:\TEMP\err.txt
  • As you can see there is extensive error logging, but the error log never gets populated (unless I put in an obvious error like a missing path)
  • Both dev and live environments are Windows
  • The line that seems to case the error is the final one - where PHP is called. When I take this out the commit works without issue
  • When I run this manually on the command line it works and doesn't show any (obvious) errors. Afaik svn runs under SYSTEM by default user which is high enough privilleges to not have to worry

As you've probably made out, this is hooking up my SVN checkins with Mantis bug tracker. The interesting thing is that the PHP script is being executed, i.e. the notes are being added to bugs and the auto-closing of issues is working. It just seems to erroring for some reason.

I am using TortoiseSVN to commit, but using command line (SlikSVN) I get the same output:

svn ci -m "this is a test" test.txt
Sending        test.txt
Transmitting file data .
Committed revision 1337.

Warning: post-commit hook failed (exit code 255) with no output.

Mantis' checkin.php looks like this (some general comments removed for readability):

#!/usr/bin/php -q
<?php

global $g_bypass_headers;
$g_bypass_headers = 1;
require_once( dirname( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' );

# Make sure this script doesn't run via the webserver
if( php_sapi_name() != 'cli' ) {
    echo "checkin.php is not allowed to run through the webserver.\n";
    exit( 1 );
}

# Check that the username is set and exists
$t_username = config_get( 'source_control_account' );
if( is_blank( $t_username ) || ( user_get_id_by_name( $t_username ) === false ) ) {
    echo "Invalid source control account ('$t_username').\n";
    exit( 1 );
}

if( !defined( "STDIN" ) ) {
    define( "STDIN", fopen( 'php://stdin', 'r' ) );
}

# Detect references to issues + concat all lines to have the comment log.
$t_commit_regexp = config_get( 'source_control_regexp' );
$t_commit_fixed_regexp = config_get( 'source_control_fixed_regexp' );

$t_comment = '';
$t_issues = array();
$t_fixed_issues = array();
while(( $t_line = fgets( STDIN, 1024 ) ) ) {
    $t_comment .= $t_line;
    if( preg_match_all( $t_commit_regexp, $t_line, $t_matches ) ) {
        $t_count = count( $t_matches[0] );
        for( $i = 0;$i < $t_count;++$i ) {
            $t_issues[] = $t_matches[1][$i];
        }
    }

    if( preg_match_all( $t_commit_fixed_regexp, $t_line, $t_matches ) ) {
        $t_count = count( $t_matches[0] );
        for( $i = 0;$i < $t_count;++$i ) {
            $t_fixed_issues[] = $t_matches[1][$i];
        }
    }
}

# If no issues found, then no work to do.
if(( count( $t_issues ) == 0 ) && ( count( $t_fixed_issues ) == 0 ) ) {
    echo "Comment does not reference any issues.\n";
    exit( 0 );
}

# Login as source control user
if( !auth_attempt_script_login( $t_username ) ) {
    echo "Unable to login\n";
    exit( 1 );
}

# history parameters are reserved for future use.
$t_history_old_value = '';
$t_history_new_value = '';

# add note to each bug only once
$t_issues = array_unique( $t_issues );
$t_fixed_issues = array_unique( $t_fixed_issues );

# Call the custom function to register the checkin on each issue.

foreach( $t_issues as $t_issue_id ) {
    if( !in_array( $t_issue_id, $t_fixed_issues ) ) {
        helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, false ) );
    }
}

foreach( $t_fixed_issues as $t_issue_id ) {
    helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, true ) );
}

exit( 0 );

Solution

  • I usually recommend not using batch scripts for Subversion hooks. There are a ton of free, open source, scripting languages that are more powerful and easier to work with. Heck, I don't even use BASH for hook scripts.

    This is especially true since hook scripts only have to run on the server and no where else. That means you only have to get it working on a single platform.


    That being said, you'll need to do some debugging. Your hook script fails via the svn commit command line. That means it's not a Tortoise related issue. It's a hook script issue. Since this is a post hook script, try running the script itself from the command line and pass to it the repository and revision from the command line:

    C> post-commit C:\repos\my_repo 2323
    

    Does that work?

    The problem is that you're not printing anything on STDERR, so there's nothing for Subversion to print. You're capturing STDERR in a file. Remove the 2>>C:\TEMP\err.txt, so you can see the error output. In Python, BASH, and Perl, I could capture STDERR, and still print it out, but I'm not sure how to do this in Batch script.

    This would allow you to see the error output, and maybe help you determine where your script is failing. Is it failing before it calls your PHP script? Is something going on in your PHP script? Are there assumptions you're making which aren't necessarily valid?

    Also, don't merely echo stuff in your PHP hook. Subversion doesn't print anything on STDOUT no matter if the hook succeeds or fails. Use fputs(STDERR, 'My Error Message'); instead of echo or print. This will send your error message to STDERR and Subversion will print it out if your hook script fails.

    Hope this helps.