2012-08-15 47 views
0

我一直在試圖讓代碼嗅探器充當svn pre-commit hook,遵循pear的指導。但是,雖然我100%肯定我的代碼應該是無效的,我得到沒有錯誤和項目提交沒有問題。代碼嗅探器SVN提交前鉤子

除了遵循梨給出的指導,還有什麼需要做的嗎?

Link to pear guide on code sniffer as pre-commit hook

我phpcs - svn的預提交的文件:

#!C:\wamp\bin\php\php5.4.3\php.exe 
<?php 
/** 
* A commit hook for SVN. 
* 
* PHP version 5 
* 
* @category PHP 
* @package PHP_CodeSniffer 
* @author Jack Bates <[email protected]> 
* @author Greg Sherwood <[email protected]> 
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600) 
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence 
* @link  http://pear.php.net/package/PHP_CodeSniffer 
*/ 

if (is_file(dirname(__FILE__).'/../CodeSniffer/CLI.php') === true) { 
    include_once dirname(__FILE__).'/../CodeSniffer/CLI.php'; 
} else { 
    include_once 'PHP/CodeSniffer/CLI.php'; 
} 

define('PHP_CODESNIFFER_SVNLOOK', 'C:\Program Files (x86)\VisualSVN Server\bin\svnlook'); 


/** 
* A class to process command line options. 
* 
* @category PHP 
* @package PHP_CodeSniffer 
* @author Jack Bates <[email protected]> 
* @author Greg Sherwood <[email protected]> 
* @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600) 
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence 
* @version Release: 1.3.6 
* @link  http://pear.php.net/package/PHP_CodeSniffer 
*/ 
class PHP_CodeSniffer_SVN_Hook extends PHP_CodeSniffer_CLI 
{ 


    /** 
    * Get a list of default values for all possible command line arguments. 
    * 
    * @return array 
    */ 
    public function getDefaults() 
    { 
     $defaults = parent::getDefaults(); 

     $defaults['svnArgs'] = array(); 
     return $defaults; 

    }//end getDefaults() 


    /** 
    * Processes an unknown command line argument. 
    * 
    * All unknown args are sent to SVN commands. 
    * 
    * @param string $arg The command line argument. 
    * @param int $pos The position of the argument on the command line. 
    * @param array $values An array of values determined from CLI args. 
    * 
    * @return array The updated CLI values. 
    * @see getCommandLineValues() 
    */ 
    public function processUnknownArgument($arg, $pos, $values) 
    { 
     $values['svnArgs'][] = escapeshellarg($arg); 
     return $values; 

    }//end processUnknownArgument() 


    /** 
    * Runs PHP_CodeSniffer over files are directories. 
    * 
    * @param array $values An array of values determined from CLI args. 
    * 
    * @return int The number of error and warning messages shown. 
    * @see getCommandLineValues() 
    */ 
    public function process($values=array()) 
    { 
     if (empty($values) === true) { 
      $values = parent::getCommandLineValues(); 
     } 

     // Get list of files in this transaction. 
     $command = PHP_CODESNIFFER_SVNLOOK.' changed '.implode(' ', $values['svnArgs']); 
     $handle = popen($command, 'r'); 
     if ($handle === false) { 
      echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; 
      exit(2); 
     } 

     $contents = stream_get_contents($handle); 
     fclose($handle); 

     // Do not check deleted paths. 
     $contents = preg_replace('/^D.*/m', null, $contents); 

     // Drop the four characters representing the action which precede the path on 
     // each line. 
     $contents = preg_replace('/^.{4}/m', null, $contents); 

     $values['standard'] = $this->validateStandard($values['standard']); 
     if (PHP_CodeSniffer::isInstalledStandard($values['standard']) === false) { 
      // They didn't select a valid coding standard, so help them 
      // out by letting them know which standards are installed. 
      echo 'ERROR: the "'.$values['standard'].'" coding standard is not installed. '; 
      $this->printInstalledStandards(); 
      exit(2); 
     } 

     $phpcs = new PHP_CodeSniffer(
      $values['verbosity'], 
      $values['tabWidth'], 
      $values['encoding'] 
     ); 

     // Set file extensions if they were specified. Otherwise, 
     // let PHP_CodeSniffer decide on the defaults. 
     if (empty($values['extensions']) === false) { 
      $phpcs->setAllowedFileExtensions($values['extensions']); 
     } 

     // Set ignore patterns if they were specified. 
     if (empty($values['ignored']) === false) { 
      $phpcs->setIgnorePatterns($values['ignored']); 
     } 

     // Set some convenience member vars. 
     if ($values['errorSeverity'] === null) { 
      $this->errorSeverity = PHPCS_DEFAULT_ERROR_SEV; 
     } else { 
      $this->errorSeverity = $values['errorSeverity']; 
     } 

     if ($values['warningSeverity'] === null) { 
      $this->warningSeverity = PHPCS_DEFAULT_WARN_SEV; 
     } else { 
      $this->warningSeverity = $values['warningSeverity']; 
     } 

     // Initialize PHP_CodeSniffer listeners but don't process any files. 
     $phpcs->setCli($this); 
     $phpcs->process(array(), $values['standard'], $values['sniffs']); 

     // Need double quotes around the following regex beause the vertical whitespace 
     // char is not always treated correctly for whatever reason. 
     foreach (preg_split("/\v|\n/", $contents, -1, PREG_SPLIT_NO_EMPTY) as $path) { 
      // No need to process folders as each changed file is checked. 
      if (substr($path, -1) === '/') { 
       continue; 
      } 

      // We need to check ignore rules ourself because they are 
      // not checked when processing a single file. 
      if ($phpcs->shouldProcessFile($path) === false) { 
       continue; 
      } 

      // Get the contents of each file, as it would be after this transaction. 
      $command = PHP_CODESNIFFER_SVNLOOK.' cat '.implode(' ', $values['svnArgs']).' '.escapeshellarg($path); 
      $handle = popen($command, 'r'); 
      if ($handle === false) { 
       echo 'ERROR: Could not execute "'.$command.'"'.PHP_EOL.PHP_EOL; 
       exit(2); 
      } 

      $contents = stream_get_contents($handle); 
      fclose($handle); 

      $phpcs->processFile($path, $contents); 
     }//end foreach 

     return $this->printErrorReport(
      $phpcs, 
      $values['reports'], 
      $values['showSources'], 
      $values['reportFile'], 
      $values['reportWidth'] 
     ); 

    }//end process() 


    /** 
    * Prints out the usage information for this script. 
    * 
    * @return void 
    */ 
    public function printUsage() 
    { 
     parent::printUsage(); 

     echo PHP_EOL; 
     echo ' Each additional argument is passed to the `svnlook changed ...`'.PHP_EOL; 
     echo ' and `svnlook cat ...` commands. The report is printed on standard output,'.PHP_EOL; 
     echo ' however Subversion displays only standard error to the user, so in a'.PHP_EOL; 
     echo ' pre-commit hook, this script should be invoked as follows:'.PHP_EOL; 
     echo PHP_EOL; 
     echo ' '.basename($_SERVER['argv'][0]).' ... "$REPOS" -t "$TXN" >&2 || exit 1'.PHP_EOL; 

    }//end printUsage() 


}//end class 

$phpcs = new PHP_CodeSniffer_SVN_Hook(); 
$phpcs->checkRequirements(); 

$numErrors = $phpcs->process(); 
if ($numErrors !== 0) { 
    exit(1); 
} 

?> 

而且從顛覆我的預提交的文件:

#!/bin/sh 

# PRE-COMMIT HOOK 
# 
# The pre-commit hook is invoked before a Subversion txn is 
# committed. Subversion runs this hook by invoking a program 
# (script, executable, binary, etc.) named 'pre-commit' (for which 
# this file is a template), with the following ordered arguments: 
# 
# [1] REPOS-PATH (the path to this repository) 
# [2] TXN-NAME  (the name of the txn about to be committed) 
# 
# [STDIN] LOCK-TOKENS ** the lock tokens are passed via STDIN. 
# 
# If STDIN contains the line "LOCK-TOKENS:\n" (the "\n" denotes a 
# single newline), the lines following it are the lock tokens for 
# this commit. The end of the list is marked by a line containing 
# only a newline character. 
# 
# Each lock token line consists of a URI-escaped path, followed 
# by the separator character '|', followed by the lock token string, 
# followed by a newline. 
# 
# The default working directory for the invocation is undefined, so 
# the program should set one explicitly if it cares. 
# 
# If the hook program exits with success, the txn is committed; but 
# if it exits with failure (non-zero), the txn is aborted, no commit 
# takes place, and STDERR is returned to the client. The hook 
# program can use the 'svnlook' utility to help it examine the txn. 
# 
# On a Unix system, the normal procedure is to have 'pre-commit' 
# invoke other programs to do the real work, though it may do the 
# work itself too. 
# 
# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT *** 
# *** FOR REVISION PROPERTIES (like svn:log or svn:author). *** 
# 
# This is why we recommend using the read-only 'svnlook' utility. 
# In the future, Subversion may enforce the rule that pre-commit 
# hooks should not modify the versioned data in txns, or else come 
# up with a mechanism to make it safe to do so (by informing the 
# committing client of the changes). However, right now neither 
# mechanism is implemented, so hook writers just have to be careful. 
# 
# Note that 'pre-commit' must be executable by the user(s) who will 
# invoke it (typically the user httpd runs as), and that user must 
# have filesystem-level permission to access the repository. 
# 
# On a Windows system, you should name the hook program 
# 'pre-commit.bat' or 'pre-commit.exe', 
# but the basic idea is the same. 
# 
# The hook program typically does not inherit the environment of 
# its parent process. For example, a common problem is for the 
# PATH environment variable to not be set to its usual value, so 
# that subprograms fail to launch unless invoked via absolute path. 
# If you're having unexpected problems with a hook program, the 
# culprit may be unusual (or missing) environment variables. 
# 
# Here is an example hook script, for a Unix /bin/sh interpreter. 
# For more examples and pre-written hooks, see those in 
# the Subversion repository at 
# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and 
# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ 


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

# Make sure that the log message contains some text. 
SVNLOOK=/usr/local/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 

C:\wamp\bin\php\php5.4.3\scripts\phpcs-svn-pre-commit "$REPOS" -t "$TXN" >&2 || exit 1 

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

我是很新的這兩個SVN和codesniffer,所以我幾乎只是遵循指南和運行測試,因爲我走了。在得到這個工作的任何意見或建議可以理解的:)

UPDATE

我設法得到了一些成果了我SVN掛鉤的,現在卻顯示了基於腳本錯誤的列表。我不熟悉SVN所需的腳本語言,所以我不知道如何解決這些問題。錯誤的

列表:

REPOS不被識別爲內部或外部命令

TXN不被識別爲內部或外部命令

未知命令 '的/ usr/local/bin中/ svnlook的'

$ svnlook的不被識別爲內部或外部命令

+0

在我看來你編輯了錯誤的文件。重新閱讀那裏的文檔,你忽略了你必須在Windows系統上編輯/執行的部分。看起來你正在使用Windows系統,對吧? – hakre 2012-08-15 09:21:43

+0

我確實使用Windows系統,Windows 7是精確的,但我真的找不到任何提及上面鏈接的指南上的窗口。另外我不知道如何有任何其他文件,只有一個phpcs-svn-pre-commit文件位於C:\ wamp \ bin \ php \ php5.4.3 \ scripts \。與mypre commit文件相同,位於C:\ repositories \ test \ hooks \上,這是我的測試庫。 – 2012-08-15 09:36:10

+0

對於故障排除,創建一個預先提交掛鉤,它向STDERR(2)輸出一些消息,並始終返回大於0的存在代碼。這將阻止所有提交。當你得到這個工作(不再有可能),你可以用具體的代碼來擺動。 – hakre 2012-08-15 09:38:17

回答

1

從您的可執行文件的路徑來看( C:\wamp\bin\php\php5.4.3\php.exe),我假設你正在使用Windows機器。

您問題中的pre-commit文件看起來像Linux Bash Shell腳本。 Bash與您在Windows下使用的批處理文件有不同的語法。

我建議你使用爲Windows機器製作的pre-commit.tmpl文件。 您可能在hooks文件夾中有這些文件。 我使用的是Linux,所以很遺憾,我不能幫助您進一步此搜索上...

pre-commit鉤看起來像這樣(從An Introduction to Subversion Hook Scripts on Windows採取摘錄):

@echo off 
:: Stops commits that don't include a log message of at least 6 characters. 
@echo off 

setlocal 

rem Subversion sends through the repository path and transaction id 
set REPOS=%1 
set TXN=%2 

svnlook log %REPOS% -t %TXN% | findstr ...... > nul 
if %errorlevel% gtr 0 (goto err) else exit 0 

:err 
echo --------------------------------------------------------------------------- 1>&2 
echo Your commit has been blocked because it didn't include a log message. 1>&2 
echo Do the commit again, this time with a log message that describes your changes. 1>&2 
echo --------------------------------------------------------------------------- 1>&2 
exit 1