r93994 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r93993‎ | r93994 | r93995 >
Date:20:28, 5 August 2011
Author:demon
Status:ok
Tags:
Comment:
Initial rewrite of pre-commit hooks, with framework for post-commit too :D
Modified paths:
  • /trunk/tools/subversion/hooks (added) (history)
  • /trunk/tools/subversion/hooks/HooksCommon.inc (added) (history)
  • /trunk/tools/subversion/hooks/pre-commit (added) (history)

Diff [purge]

Index: trunk/tools/subversion/hooks/HooksCommon.inc
@@ -0,0 +1,177 @@
 2+<?php
 3+/**
 4+ * Utility class for things relating to commits and their tests.
 5+ */
 6+class CommitInfo {
 7+ /**
 8+ * Subversion repository path
 9+ * @var string
 10+ */
 11+ protected $repo;
 12+
 13+ /**
 14+ * Transaction number
 15+ * @var int
 16+ */
 17+ protected $transaction;
 18+
 19+ /**
 20+ * Location of svnlook, in case it's not in $PATH
 21+ * @var string
 22+ */
 23+ protected $svnlook = '/opt/local/bin/svnlook';
 24+
 25+ /**
 26+ * Location of PHP binary, in case it's not in $PATH
 27+ * @var string
 28+ */
 29+ protected $php = '/opt/local/bin/php';
 30+
 31+ /**
 32+ * Tests to run, with their configuration
 33+ */
 34+ protected $preCommitTests = array(
 35+ 'testLogMessageLength' => array(
 36+ 1, /** min length **/
 37+ '[a-z0-9]+' /** regex to check **/
 38+ ),
 39+ 'testPHPLint' => array(
 40+ array( 'php', 'php5', 'phtml', 'inc' ), /** valid types to check **/
 41+ ),
 42+ );
 43+
 44+ /**
 45+ * Places to ping after a commit has completed (CR, CI, etc)
 46+ */
 47+ protected $postCommitPings = array(
 48+
 49+ );
 50+
 51+ /**
 52+ * Class constructor
 53+ *
 54+ * @param $repository String name of repository
 55+ * @param $transaction
 56+ * @param array $tests array of test names to run
 57+ */
 58+ public function __construct( $repo, $txn ) {
 59+ $this->repo = $repo;
 60+ $this->transaction = $txn;
 61+ }
 62+
 63+ /**
 64+ * Run SVN pre-commit tests
 65+ */
 66+ public function runPreCommitTests() {
 67+ $result = 0;
 68+ $messages = '';
 69+ foreach( $this->preCommitTests as $test => $params ) {
 70+ $msg = call_user_func_array( array( $this, $test ), $params );
 71+ if( $msg !== true ) {
 72+ $messages .= "$msg\n";
 73+ $result++;
 74+ }
 75+ }
 76+ if ( $result ) {
 77+ $messages = rtrim( $messages );
 78+ fwrite( STDERR, "----------------\n$messages\n----------------" );
 79+ }
 80+ return $result;
 81+ }
 82+
 83+ /**
 84+ * Get commit log message
 85+ *
 86+ * @return string
 87+ */
 88+ private function getLogMessage() {
 89+ $output = null;
 90+ $cmd = "{$this->svnlook} log -t '{$this->transaction}' '{$this->repo}'";
 91+ exec( $cmd, $output );
 92+ return implode( $output );
 93+ }
 94+
 95+ /**
 96+ * Get commit files list
 97+ *
 98+ * @return array filenames are keys and status letters are values
 99+ */
 100+ protected function getCommitList() {
 101+ $output = null;
 102+ $cmd = "{$this->svnlook} changed -t '{$this->transaction}' '{$this->repo}'";
 103+ exec( $cmd, $output );
 104+
 105+ $list = array();
 106+ foreach( $output as $item ) {
 107+ $pos = strpos( $item, ' ' );
 108+ $status = substr( $item, 0, $pos );
 109+ $file = trim( substr( $item, $pos ) );
 110+ $list[$file] = $status;
 111+ }
 112+ return $list;
 113+ }
 114+
 115+ /**
 116+ * Get array of modified and added files
 117+ *
 118+ * @param $fileTypes array of file types used for filtering
 119+ * @return array
 120+ */
 121+ protected function getChangedFiles( array $fileTypes = array() ) {
 122+ $list = $this->getCommitList();
 123+ $files = array();
 124+ foreach ( $list as $file => $status ) {
 125+ if ( 'D' == $status || substr( $file, -1 ) == DIRECTORY_SEPARATOR ) {
 126+ continue;
 127+ }
 128+ $files[] = $file;
 129+ }
 130+
 131+ $matchingChangedFiles = array();
 132+ foreach( $files as $file ) {
 133+ $extension = strtolower( pathinfo( $file, PATHINFO_EXTENSION ) );
 134+ if ( $fileTypes && !in_array( $extension, $fileTypes ) ) {
 135+ continue;
 136+ }
 137+ $matchingChangedFiles[$file] = $extension;
 138+ }
 139+ return $matchingChangedFiles;
 140+ }
 141+
 142+ /**
 143+ * Check if log message validates length rules
 144+ *
 145+ * @param int $minlength minimum length of log message
 146+ * @return bool
 147+ */
 148+ protected function testLogMessageLength( $minLength = 1, $regex = '' ) {
 149+ $msg = trim( $this->getLogMessage() );
 150+ $length = strlen( $msg );
 151+ if ( $length < $minLength ) {
 152+ if ( $minLength <= 1 ) {
 153+ return "Log message should not be empty. Please specify descriptive log message.";
 154+ } else {
 155+ return "You log message is too short ($length). It should be at least $minlength characters long.";
 156+ }
 157+ } elseif( !preg_match( "/$regex/i", $msg ) ) {
 158+ return "Please provide a descriptive commit message with letters.";
 159+ }
 160+ return true;
 161+ }
 162+
 163+ protected function testPHPLint( $fileTypes ) {
 164+ $output = null;
 165+ $result = '';
 166+ $changedFiles = $this->getChangedFiles( $fileTypes );
 167+ foreach( $changedFiles as $file => $ext ) {
 168+ $cmd = "{$this->php} -l $file";
 169+ exec( $cmd, $output );
 170+ foreach( $output as $item ) {
 171+ if( strpos( trim( $item ), 'No syntax errors detected in' ) === false ) {
 172+ $result .= "$item\n";
 173+ }
 174+ }
 175+ }
 176+ return $result !== '' ? $result : true;
 177+ }
 178+}
Property changes on: trunk/tools/subversion/hooks/HooksCommon.inc
___________________________________________________________________
Added: svn:eol-style
1179 + native
Index: trunk/tools/subversion/hooks/pre-commit
@@ -0,0 +1,9 @@
 2+#!/usr/bin/php
 3+<?php
 4+
 5+require( "HooksCommon.inc" );
 6+$repo = $argv[1];
 7+$txn = $argv[2];
 8+
 9+$preCommit = new CommitInfo( $repo, $txn );
 10+exit( $preCommit->runPreCommitTests() );

Follow-up revisions

RevisionCommit summaryAuthorDate
r93995Update for usual locations of svnlook and php binariesdemon20:29, 5 August 2011
r93996rm leftover comment from the code I hijackeddemon20:33, 5 August 2011
r93997Fix undefined variable, fixup documentation...reedy20:35, 5 August 2011

Status & tagging log