(bug 35749) Update checkSyntax.php to use Git
authorKevin Israel <pleasestand@live.com>
Fri, 6 Apr 2012 04:13:46 +0000 (00:13 -0400)
committerKevin Israel <pleasestand@live.com>
Fri, 6 Apr 2012 04:36:39 +0000 (00:36 -0400)
checkSyntax.php now uses git commands to retrieve a list of modified
files instead of the svn command-line client.

The script now considers any files that have been changed since
the nearest common ancestor to the master branch to be "modified",
as it is probably desirable to include files modified in previous
commits on the same local topic branch that have not yet made it
into master.

Change-Id: I0d4a02d4591242a9fd45291f5c4230c535e861b3

RELEASE-NOTES-1.20
maintenance/checkSyntax.php

index 9c05349..921ac00 100644 (file)
@@ -72,6 +72,8 @@ production.
 * (bug 35680) jQuery upgraded to 1.7.2.
 * (bug 35681) jQuery UI upgraded to 1.8.18.
 * (bug 35705) QUnit upgraded from 1.2.0 to 1.5.0
+* (bug 35749) Updated maintenance/checkSyntax.php to use Git instead of
+  Subversion when invoked with the --modified option.
 
 === API changes in 1.20 ===
 * (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.
index cc4e5af..6137a95 100644 (file)
@@ -36,7 +36,7 @@ class CheckSyntax extends Maintenance {
                $this->addOption( 'path', 'Specific path (file or directory) to check, either with absolute path or relative to the root of this MediaWiki installation',
                        false, true );
                $this->addOption( 'list-file', 'Text file containing list of files or directories to check', false, true );
-               $this->addOption( 'modified', 'Check only files that were modified (requires SVN command-line client)' );
+               $this->addOption( 'modified', 'Check only files that were modified (requires Git command-line client)' );
                $this->addOption( 'syntax-only', 'Check for syntax validity only, skip code style warnings' );
        }
 
@@ -114,18 +114,10 @@ class CheckSyntax extends Maintenance {
                        fclose( $f );
                        return;
                } elseif ( $this->hasOption( 'modified' ) ) {
-                       $this->output( "Retrieving list from Subversion... " );
-                       $parentDir = wfEscapeShellArg( dirname( __FILE__ ) . '/..' );
-                       $retval = null;
-                       $output = wfShellExec( "svn status --ignore-externals $parentDir", $retval );
-                       if ( $retval ) {
-                               $this->error( "Error retrieving list from Subversion!\n", true );
-                       } else {
-                               $this->output( "done\n" );
-                       }
-
-                       preg_match_all( '/^\s*[AM].{7}(.*?)\r?$/m', $output, $matches );
-                       foreach ( $matches[1] as $file ) {
+                       $this->output( "Retrieving list from Git... " );
+                       $files = $this->getGitModifiedFiles( $IP );
+                       $this->output( "done\n" );
+                       foreach ( $files as $file ) {
                                if ( $this->isSuitableFile( $file ) && !is_dir( $file ) ) {
                                        $this->mFiles[] = $file;
                                }
@@ -163,6 +155,59 @@ class CheckSyntax extends Maintenance {
                $this->output( 'done.', 'listfiles' );
        }
 
+       /**
+        * Returns a list of tracked files in a Git work tree differing from the master branch.
+        * @param $path string: Path to the repository
+        * @return array: Resulting list of changed files
+        */
+       private function getGitModifiedFiles( $path ) {
+
+               global $wgMaxShellMemory;
+
+               if ( !is_dir( "$path/.git" ) ) {
+                       $this->error( "Error: Not a Git repository!\n", true );
+               }
+
+               // git diff eats memory.
+               $oldMaxShellMemory = $wgMaxShellMemory;
+               if ( $wgMaxShellMemory < 1024000 ) {
+                       $wgMaxShellMemory = 1024000;
+               }
+
+               $ePath = wfEscapeShellArg( $path );
+
+               // Find an ancestor in common with master (rather than just using its HEAD)
+               // to prevent files only modified there from showing up in the list.
+               $cmd = "cd $ePath && git merge-base master HEAD";
+               $retval = 0;
+               $output = wfShellExec( $cmd, $retval );
+               if ( $retval !== 0 ) {
+                       $this->error( "Error retrieving base SHA1 from Git!\n", true );
+               }
+
+               // Find files in the working tree that changed since then.
+               $eBase = wfEscapeShellArg( rtrim( $output, "\n" ) );
+               $cmd = "cd $ePath && git diff --name-only --diff-filter AM $eBase";
+               $retval = 0;
+               $output = wfShellExec( $cmd, $retval );
+               if ( $retval !== 0 ) {
+                       $this->error( "Error retrieving list from Git!\n", true );
+               }
+
+               $wgMaxShellMemory = $oldMaxShellMemory;
+
+               $arr = array();
+               $filename = strtok( $output, "\n" );
+               while ( $filename !== false ) {
+                       if ( $filename !== '' ) {
+                               $arr[] = "$path/$filename";
+                       }
+                       $filename = strtok( "\n" );
+               }
+
+               return $arr;
+       }
+
        /**
         * Returns true if $file is of a type we can check
         * @param $file string