少用的 - 用其它语言写钩子

  • 作者:KK

  • 发表日期:2015.12.27


你是不是就疑惑"那我不是要学bat的编程?"其实不用啦,你只要能写现通过shell返回结果码给SVN,管你用python还是PHP还是什么呢?

下面我举例子使用PHP做钩子

重新操作上一章的钩子设置,这回在要执行的命令行里我们不写一个bat文件路径了,而是写php E:\on-commit.php这样的PHP命令,然后编写E:\on-commit.php代码如下:

$logMessage = trim(file_get_contents($argv[3])); //取出提交的日志消息
if(mb_strlen($logMessage, 'UTF-8') < 5){
	$errorOutputHandler = fopen('php://stderr', 'w');
	fwrite($errorOutputHandler, '请填写日志信息,5个字以上');
	fclose($errorOutputHandler);
	exit(1);
}


$normalOutputHandler = fopen('php://stdout', 'w');
fwrite($normalOutputHandler, '恭喜你成功通过PHP的SVN钩子检测!');
fclose($normalOutputHandler);
exit(0);

然后试下提交的时候不要填写日志消息或者5个字以下,则会受到提醒

那么其它语言就自己发挥了,你擅长哪种语言就用哪种吧


由于我是做WEB项目多,所以下面我附上一个自己写的PHP钩子分享,你可以拿去按照自己项目的实际需求修改一下进行应用

以下并不是我在实际项目中应用的钩子代码,差异会很大,而且有时会引用一些框架做高级点的检测事情,只是我按照一般性检查和处理需求写的一个演示脚本

define('PROJECT_PATH', $argv[4]);
define('ERR_CONFIG_NOT_EXIST', 1);
define('ERR_CANNOT_COMMIT_FILE', 2);
define('ERR_MESSAGE_LENGTH_ENOUTH', 3);
define('ERR_PHP_SYTANX', 4);
define('ERR_JS_COMPRESS', 5);
define('ERR_CSS_COMPRESS', 6);
define('SUCCESS', 0);

$connotCommitFiles = array(
	'config-local.xml',
	'lib/TestStorage.php',
	'web/assets/core.js',
);

$normalOutputHandler = fopen('php://stdout', 'w');
$errorOutputHandler = fopen('php://stderr', 'w');
if(!is_file(PROJECT_PATH . '/config.xml')){
	putMsg('关键配置文件不存在!请确认是否误删');
	returnResult(ERR_CONFIG_NOT_EXIST);
}

$logMessage = trim(file_get_contents($argv[3])); //取出提交的日志消息
if(mb_strlen($logMessage, 'UTF-8') < 5){
	putMsg('请填写日志信息,5个字以上');
	returnResult(ERR_MESSAGE_LENGTH_ENOUTH);
}

$commitFiles = file($argv[1]);
$sytanxErrorFiles = array();
$jsFiles = array();
foreach($commitFiles as $commitFile){
	$commitFile = str_replace('\\', '/', $commitFile);
	if(in_array(
		str_replace(PROJECT_PATH, '', $commitFile),
		$connotCommitFiles
	)){
		putMsg($commitFile . ' 此文件在禁止提交的列表中!请确认不是误提交');
		returnResult(ERR_CANNOT_COMMIT_FILE);
	}
	
	$fileSuffix = substr($commitFile, -4);
	if($fileSuffix == '.php'){
		//PHP文件语法检查
		exec('php -l ' . $commitFile, $output, $sytanxResultCode);
		if($sytanxResultCode){
			$commitFile = str_replace(PROJECT_PATH, '', $commitFile);
			$sytanxErrorFiles[] = $commitFile . ":\n\t\t" . implode("\n\t\t", $output);
		}
		
	}elseif($fileSuffix == '.js'){
		$jsFiles[] = $commitFile;
	}
	//更多什么CSS呀那些自己弄弄
}


if($sytanxErrorFiles){
	$fileList = implode("\n\t" . $sytanxErrorFiles);
	putMsg("以下PHP文件存在语法错误:\n\t" . $fileList);
	returnResult(ERR_PHP_SYTANX);
}

if($jsFiles){
	//接下来压缩CSS,要先准备yuicompress
	$compressCmd = 'java -jar E:\yuicompressor.jar --type js --charset utf-8 -v ';
	foreach($jsFiles as $jsFile){
		$compressJsFile = preg_replace('#(.+)(\.js)$#', '$1.min$2', $jsFile);
		exec("$compressCmd $jsFile > $compressJsFile", $output, $compressResultCode);
		if($compressResultCode){
			putMsg(implode(PHP_EOL, $output));
			returnResult(ERR_JS_COMPRESS);
		}
	}
}

returnResult(SUCCESS);


function putMsg($msg, $isError = true){
	global $normalOutputHandler, $errorOutputHandler;
	$msg .= PHP_EOL;
	if($isError){
		fwrite($errorOutputHandler, $msg);
	}else{
		fwrite($normalOutputHandler, $msg);
	}
}

function returnResult($resultCode){
	global $normalOutputHandler, $errorOutputHandler;
	fclose($normalOutputHandler);
	fclose($errorOutputHandler);
	exit($resultCode);
}