You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@subversion.apache.org by ma...@externe.bnpparibas.com on 2008/02/29 09:12:29 UTC

Réf. : Re: svnlook log doesn't return message

Hello,
thanks for your feedback

So my pre-commit script is a bat file which call a php script file:
here's the bat content:
*****************************************************
@echo off
rem pre commit hook script
rem only two parameters are pass to this script: transaction number and 
repository folder
rem 
rem this bat is run with apache acces right
rem
rem output must be throw to stderr
rem

:run
"D:\php\php.exe" %~dp0pre-commit.php %1 %2
*****************************************************

and here the pre-commit.php script content:
******************************************************************
<?php
/**
 * $Id: pre-commit.php 7 2008-02-28 12:47:15Z myuser $
 */
/**
 * How does it work?
 * Before files commit, we does our controls. if something is wrong, we 
have an error and return code is diffrent than 0
 *
 * Under windows, the output message must be wrote on STDERR to be display 
to client
 * @author Matthieu MARY
 */
 
/**
 * errors codes
 */
define('__ERROR_CODE_OK__', 0);
define('__TECHNICAL_ERROR__', 1); // erreur technique
define('__ERROR_CODE_PARSE_ERROR__', 2); // error parsing php file
define('__ERROR_CODE_LOG_MESSAGE_EMPTY__', 3); // error when message is 
empty
define('__ERROR_FILES_NOT_ALLOWED__', 4); // error file is not allowed

/**
 * controls to do
 */
// does we need to control log message?
define('__CONTROL_COMMIT_MESSAGE__', true);
// does we need to check php parsing validity?
define('__CONTROL_PHP_FILE__', false);
// does we need to check if there is some files not allowed?
define('__CONTROL_NOT_ALLOWED_FILES__', true); 

/**
 * controls required to 
 */
define('__REPOS__', $_SERVER['argv'][1]); // repository path
define('__TXN__', $_SERVER['argv'][2]); // the transaction number
define('__SVN_LOOK_PATH__', 'C:\svn\bin\svnlook.exe'); // full path to 
svnlook
define('__PHP_PATH__', 'D:\php\php.exe'); // full path to php client
/**
 * just a class that display error in stderr
 */ 
class Error 
{
        /**
         * @ccess public
         * @param string $msg the error message
         * @param int $code the error code 
         */
        function Display($msg, $code) 
        {
                $fp = fopen('php://stderr', 'w');
                fwrite($fp, "********** " .$msg." (code d'erreur: 
".$code.") **********");
                fclose($fp);
                exit($code);
        }

}

        /**
         * check if there is all parameters
         */
        if ($_SERVER['argc'] != 3) {
                Error :: Display("Technical error", __TECHNICAL_ERROR__);
        }

        /**
         * check the php content
         */
        if (__CONTROL_PHP_FILE__) 
        {
                /**
                 * fetch the file list
                 *  this command run "C:\svn\bin\svnlook.exe" changed -t 
1-1 D:\repositories/myproject
                 */
                $cmd = exec(escapeshellarg(__SVN_LOOK_PATH__)." changed -t 
".__TXN__." ".__REPOS__);
                if (preg_match_all("/[A-Z]\s+(trunk\/.+php)$/i", $cmd, 
$matches)) {
                        /**
                         * foreach php file commited
                         */
                        foreach($matches[1] as $file) {
                                $output = array();
                                /**
                                 * we fetch the php content of the file in 
transaction and parse it with php client
                                         * this command run 
"C:\svn\bin\svnlook.exe" cat -t 1-1 "D:\repositories/myproject" "%myfile%" 
| "D:\php\php.exe" -l 
                                 */
                                $cmd = escapeshellarg(__SVN_LOOK_PATH__)." 
cat -t ".__TXN__." ".escapeshellarg(__REPOS__)." ".escapeshellarg($file)." 
| ".escapeshellarg(__PHP_PATH__)." -l";
                                $cmd = exec($cmd, $output, $returnVar);
                                if ($returnVar > 0) {
                                        Error :: Display("Your file $file 
contains errors, transaction aborded", $returnVar);
                                }
                        }
                }
        }
        /**
         * check some not allowed files
         */
        if (__CONTROL_NOT_ALLOWED_FILES__) {
                /**
                 * fetch file list in transaction
                 * this command run "C:\svn\bin\svnlook.exe" changed -t 
1-1 D:\repositories/myproject
                 */
                $cmd = exec(escapeshellarg(__SVN_LOOK_PATH__)." changed -t 
".__TXN__." ".__REPOS__);
                /**
                 * just check files add for the first time
                 */
                if (!preg_match_all("/[A]\s+([^\s]+)$/i", $cmd, $matches)) 
{
                        $notAllowedFiles = array("/\.project$/", 
"/thumbs\.db/i", "/\.svn/", "/.+\.log$/","/.+\.bak$/", 
"/.+\.old$/","/cache\/[a-z0-9A-Z]+\.png$/");
                        /**
                         * foreach file add
                         */
                        foreach($matches[1] as $file) {
                                foreach($notAllowedFiles as 
$currentPattern) {
                                        /**
                                         * if file is not allowed
                                         */
                                        if (preg_match($currentPattern, 
$file)) {
                                                Error :: Display("You try 
to add some files not allowed($currentPattern)", 
__ERROR_FILES_NOT_ALLOWED__);
                                        }
                                }
                        }
                }
        }
        /**
         * check if we have a message in transaction
         */
        if (__CONTROL_COMMIT_MESSAGE__) 
        {
                /**
                 * This command run "C:\svn\bin\svnlook.exe" log -t 1-1 
D:\repositories/myproject
                 */
                $cmd = trim(exec(escapeshellarg(__SVN_LOOK_PATH__)." log 
-t ".__TXN__." ".__REPOS__));
                if (!preg_match("/[a-zA-Z0-9]+/", $cmd, $matches)) 
                {
                        Error :: Display("You should set a message in your 
commit", __ERROR_CODE_LOG_MESSAGE_EMPTY__);
                }
 
        }

exit(__ERROR_CODE_OK__);
?>
*******************************************************
Hope this code won't be too much hard to understand for non php users.

But I'm not sure that is a pre-commit script problem because I'have made 
the same thing this morning in same circumstancies (initial import on 
trunk folder) for a new repository project, and this time, I had no error 
(error always happened for the repository that gave me error).

Best regards,

Matthieu




Internet 
subversion-2008a@ryandesign.com
28/02/2008 23:22

Pour
Matthieu MARY
cc
users@subversion.tigris.org
Objet
Re: svnlook log doesn't return message






On Feb 28, 2008, at 09:56, matthieu.mary@externe.bnpparibas.com wrote:

> [Thu Feb 28 16:09:05 2008] [error] [client 192.168.10.2] 'pre- 
> commit' hook failed with error output:\n**********  You should set 
> a log message (error code: 3) **********  [409, #165001]
>
> Could you help me please? There something I don't understand, but 
> don't know why and have look for solution in ressources without 
> succes.

If you're absolutely sure you're specifying a log message, then it 
sounds like a problem in your pre-commit hook script. So you'll have 
to show us your pre-commit hook script so we can help you debug it.





This message and any attachments (the "message") is
intended solely for the addressees and is confidential. 
If you receive this message in error, please delete it and 
immediately notify the sender. Any use not in accord with 
its purpose, any dissemination or disclosure, either whole 
or partial, is prohibited except formal approval. The internet
can not guarantee the integrity of this message. 
BNP PARIBAS (and its subsidiaries) shall (will) not 
therefore be liable for the message if modified. 
Do not print this message unless it is necessary,
consider the environment.

                ---------------------------------------------

Ce message et toutes les pieces jointes (ci-apres le 
"message") sont etablis a l'intention exclusive de ses 
destinataires et sont confidentiels. Si vous recevez ce 
message par erreur, merci de le detruire et d'en avertir 
immediatement l'expediteur. Toute utilisation de ce 
message non conforme a sa destination, toute diffusion 
ou toute publication, totale ou partielle, est interdite, sauf 
autorisation expresse. L'internet ne permettant pas 
d'assurer l'integrite de ce message, BNP PARIBAS (et ses
filiales) decline(nt) toute responsabilite au titre de ce 
message, dans l'hypothese ou il aurait ete modifie.
N'imprimez ce message que si necessaire,
pensez a l'environnement.

Réf. : Re: svnlook log doesn't return message

Posted by ma...@externe.bnpparibas.com.
Hello,

sure you are right about the fact I was in some case testing the ouput, 
and sometimes testing return code.
My problem was that I doesn't understand that exec returns only the last 
line :)
My pre-commit.php works better now:
Thanks for your help
Best regards 

Matthieu




Internet 
subversion-2008a@ryandesign.com
29/02/2008 11:06

Pour
Matthieu MARY
cc
users@subversion.tigris.org
Objet
Re: svnlook log doesn't return message






On Feb 29, 2008, at 03:48, Ryan Schmidt wrote:

> And of course right after I sent my reply, I thought a bit more 
> about the problem and realized that because you're using the return 
> value from exec(), which is just the last line of output, you're 
> only checking the last line of the log message. If you have a nice 
> long log message but it ends with a blank line (for example if it 
> was composed in an editor like mine which always makes sure that 
> every saved file ends with a blank line), your script will think 
> you entered no log message, and will issue an error. You should be 
> checking the entire output of svnlook log, not just the last line.

And for the same reason, your php lint checker is only checking the 
last file in the list.

And for the same reason, your not-allowed-filename checker is only 
checking the last file in the list. Also, from the comments it sounds 
like you want to check only files that are being added, which makes 
sense. But your code only checks a file *unless* it's being added. To 
fix this, this line:

if (!preg_match_all("/[A]\s+([^\s]+)$/i", $cmd, $matches)) {

should be changed to

if (preg_match_all("/[A]\s+([^\s]+)$/i", $cmd, $matches)) {





This message and any attachments (the "message") is
intended solely for the addressees and is confidential. 
If you receive this message in error, please delete it and 
immediately notify the sender. Any use not in accord with 
its purpose, any dissemination or disclosure, either whole 
or partial, is prohibited except formal approval. The internet
can not guarantee the integrity of this message. 
BNP PARIBAS (and its subsidiaries) shall (will) not 
therefore be liable for the message if modified. 
Do not print this message unless it is necessary,
consider the environment.

                ---------------------------------------------

Ce message et toutes les pieces jointes (ci-apres le 
"message") sont etablis a l'intention exclusive de ses 
destinataires et sont confidentiels. Si vous recevez ce 
message par erreur, merci de le detruire et d'en avertir 
immediatement l'expediteur. Toute utilisation de ce 
message non conforme a sa destination, toute diffusion 
ou toute publication, totale ou partielle, est interdite, sauf 
autorisation expresse. L'internet ne permettant pas 
d'assurer l'integrite de ce message, BNP PARIBAS (et ses
filiales) decline(nt) toute responsabilite au titre de ce 
message, dans l'hypothese ou il aurait ete modifie.
N'imprimez ce message que si necessaire,
pensez a l'environnement.

Re: svnlook log doesn't return message

Posted by Ryan Schmidt <su...@ryandesign.com>.
On Feb 29, 2008, at 03:48, Ryan Schmidt wrote:

> And of course right after I sent my reply, I thought a bit more  
> about the problem and realized that because you're using the return  
> value from exec(), which is just the last line of output, you're  
> only checking the last line of the log message. If you have a nice  
> long log message but it ends with a blank line (for example if it  
> was composed in an editor like mine which always makes sure that  
> every saved file ends with a blank line), your script will think  
> you entered no log message, and will issue an error. You should be  
> checking the entire output of svnlook log, not just the last line.

And for the same reason, your php lint checker is only checking the  
last file in the list.

And for the same reason, your not-allowed-filename checker is only  
checking the last file in the list. Also, from the comments it sounds  
like you want to check only files that are being added, which makes  
sense. But your code only checks a file *unless* it's being added. To  
fix this, this line:

if (!preg_match_all("/[A]\s+([^\s]+)$/i", $cmd, $matches)) {

should be changed to

if (preg_match_all("/[A]\s+([^\s]+)$/i", $cmd, $matches)) {


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org

Re: svnlook log doesn't return message

Posted by Ryan Schmidt <su...@ryandesign.com>.
On Feb 29, 2008, at 03:39, Ryan Schmidt wrote:

> On Feb 29, 2008, at 03:12, matthieu.mary@externe.bnpparibas.com wrote:
>
>>         /**
>>          * check if we have a message in transaction
>>          */
>>         if (__CONTROL_COMMIT_MESSAGE__)
>>         {
>>                 /**
>>                  * This command run "C:\svn\bin\svnlook.exe" log - 
>> t 1-1 D:\repositories/myproject
>>                  */
>>                 $cmd = trim(exec(escapeshellarg 
>> (__SVN_LOOK_PATH__)." log -t ".__TXN__." ".__REPOS__));
>>                 if (!preg_match("/[a-zA-Z0-9]+/", $cmd, $matches))
>>                 {
>>                         Error :: Display("You should set a message  
>> in your commit", __ERROR_CODE_LOG_MESSAGE_EMPTY__);
>>                 }
>>
>>         }

[snip]

> $output = array();
> $cmd = trim(exec(escapeshellarg(__SVN_LOOK_PATH__)." log -t  
> ".__TXN__." ".__REPOS__."2>&1", $output, $returnVar));
>
> $cmd is just going to contain the last line of output, while implode 
> ("\n", $output) will be all lines of output (you never know, the  
> error output may be more than one line...).

[snip]

And of course right after I sent my reply, I thought a bit more about  
the problem and realized that because you're using the return value  
from exec(), which is just the last line of output, you're only  
checking the last line of the log message. If you have a nice long  
log message but it ends with a blank line (for example if it was  
composed in an editor like mine which always makes sure that every  
saved file ends with a blank line), your script will think you  
entered no log message, and will issue an error. You should be  
checking the entire output of svnlook log, not just the last line.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org

Re: svnlook log doesn't return message

Posted by Ryan Schmidt <su...@ryandesign.com>.
I tried your pre-commit.php on my Mac and it looks mostly ok...

On Feb 29, 2008, at 03:12, matthieu.mary@externe.bnpparibas.com wrote:

>         /**
>          * check the php content
>          */
>         if (__CONTROL_PHP_FILE__)
>         {
>                 /**
>                  * fetch the file list
>                  *  this command run "C:\svn\bin\svnlook.exe"  
> changed -t 1-1 D:\repositories/myproject
>                  */
>                 $cmd = exec(escapeshellarg(__SVN_LOOK_PATH__)."  
> changed -t ".__TXN__." ".__REPOS__);

You're not checking the exit status of the svnlook command, which  
would be given in the 3rd parameter of exec. svnlook could fail...  
you never know...

>                 if (preg_match_all("/[A-Z]\s+(trunk\/.+php)$/i",  
> $cmd, $matches)) {
>                         /**
>                          * foreach php file commited
>                          */
>                         foreach($matches[1] as $file) {
>                                 $output = array();
>                                 /**
>                                  * we fetch the php content of the  
> file in transaction and parse it with php client
>                                           * this command run "C:\svn 
> \bin\svnlook.exe" cat -t 1-1 "D:\repositories/myproject" "%myfile%"  
> | "D:\php\php.exe" -l
>                                  */
>                                 $cmd = escapeshellarg 
> (__SVN_LOOK_PATH__)." cat -t ".__TXN__." ".escapeshellarg 
> (__REPOS__)." ".escapeshellarg($file)." | ".escapeshellarg 
> (__PHP_PATH__)." -l";
>                                 $cmd = exec($cmd, $output,  
> $returnVar);
>                                 if ($returnVar > 0) {
>                                         Error :: Display("Your file  
> $file contains errors, transaction aborded", $returnVar);
>                                 }
>                         }
>                 }
>         }
>         /**
>          * check some not allowed files
>          */
>         if (__CONTROL_NOT_ALLOWED_FILES__) {
>                 /**
>                  * fetch file list in transaction
>                  * this command run "C:\svn\bin\svnlook.exe"  
> changed -t 1-1 D:\repositories/myproject
>                  */
>                 $cmd = exec(escapeshellarg(__SVN_LOOK_PATH__)."  
> changed -t ".__TXN__." ".__REPOS__);

Same here...

>                 /**
>                  * just check files add for the first time
>                  */
>                 if (!preg_match_all("/[A]\s+([^\s]+)$/i", $cmd,  
> $matches)) {
>                         $notAllowedFiles = array("/\.project$/", "/ 
> thumbs\.db/i", "/\.svn/", "/.+\.log$/","/.+\.bak$/", "/.+\.old$/","/ 
> cache\/[a-z0-9A-Z]+\.png$/");
>                         /**
>                          * foreach file add
>                          */
>                         foreach($matches[1] as $file) {
>                                 foreach($notAllowedFiles as  
> $currentPattern) {
>                                         /**
>                                           * if file is not allowed
>                                           */
>                                         if (preg_match 
> ($currentPattern, $file)) {
>                                                 Error :: Display 
> ("You try to add some files not allowed($currentPattern)",  
> __ERROR_FILES_NOT_ALLOWED__);
>                                         }
>                                 }
>                         }
>                 }
>         }
>         /**
>          * check if we have a message in transaction
>          */
>         if (__CONTROL_COMMIT_MESSAGE__)
>         {
>                 /**
>                  * This command run "C:\svn\bin\svnlook.exe" log -t  
> 1-1 D:\repositories/myproject
>                  */
>                 $cmd = trim(exec(escapeshellarg 
> (__SVN_LOOK_PATH__)." log -t ".__TXN__." ".__REPOS__));

Same here...

>                 if (!preg_match("/[a-zA-Z0-9]+/", $cmd, $matches))
>                 {
>                         Error :: Display("You should set a message  
> in your commit", __ERROR_CODE_LOG_MESSAGE_EMPTY__);
>                 }
>
>         }
>
> exit(__ERROR_CODE_OK__);
> ?>
> *******************************************************
> Hope this code won't be too much hard to understand for non php users.
>
> But I'm not sure that is a pre-commit script problem because I'have  
> made the same thing this morning in same circumstancies (initial  
> import on trunk folder) for a new repository project, and this  
> time, I had no error (error always happened for the repository that  
> gave me error).

I'm guessing that svnlook is sometimes giving you an error message,  
but you're not checking its exit status or the returned error message  
so your code is just failing later on. You should check each exec's  
exit status, and if it's non-zero, do something with the returned  
error message, like either display it to the user or log it away in a  
file.

Note you'll have to capture stderr from the exec'd process with  
"2>&1" if you want the error message returned to you, like this:

$output = array();
$cmd = trim(exec(escapeshellarg(__SVN_LOOK_PATH__)." log -t  
".__TXN__." ".__REPOS__."2>&1", $output, $returnVar));

$cmd is just going to contain the last line of output, while implode 
("\n", $output) will be all lines of output (you never know, the  
error output may be more than one line...).

Your repository path doesn't contain spaces or quotes or special  
characters or anything does it? If it did, you would need to  
escapeshellarg(__REPOS__) when putting it into a command.

Confusing that you're sometimes using $cmd for the command that will  
be executed, and sometimes for the value returned from that command...


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@subversion.tigris.org
For additional commands, e-mail: users-help@subversion.tigris.org