Get conflict results from diff3
authorWMDE-Fisch <christoph.jauera@wikimedia.de>
Thu, 29 Dec 2016 14:08:54 +0000 (15:08 +0100)
committeraddshore <addshorewiki@gmail.com>
Wed, 6 Dec 2017 12:25:35 +0000 (13:25 +0100)
This patch extends the global wfMerge function to also return the
result of the first merge attempt that detects merge conflicts.

The additional output explicitly names the conflicting lines and
could help when solving edit conflicts.

Bug: T151320
Change-Id: I97acebdc87b31779200c7fde4dd4449cd1ee8ead

includes/GlobalFunctions.php
tests/phpunit/includes/GlobalFunctions/GlobalTest.php

index bb1951d..1a33b76 100644 (file)
@@ -2404,9 +2404,10 @@ function wfShellWikiCmd( $script, array $parameters = [], array $options = [] )
  * @param string $mine
  * @param string $yours
  * @param string &$result
+ * @param string &$mergeAttemptResult
  * @return bool
  */
-function wfMerge( $old, $mine, $yours, &$result ) {
+function wfMerge( $old, $mine, $yours, &$result, &$mergeAttemptResult = null ) {
        global $wgDiff3;
 
        # This check may also protect against code injection in
@@ -2442,13 +2443,18 @@ function wfMerge( $old, $mine, $yours, &$result ) {
                $oldtextName, $yourtextName );
        $handle = popen( $cmd, 'r' );
 
-       if ( fgets( $handle, 1024 ) ) {
-               $conflict = true;
-       } else {
-               $conflict = false;
-       }
+       $mergeAttemptResult = '';
+       do {
+               $data = fread( $handle, 8192 );
+               if ( strlen( $data ) == 0 ) {
+                       break;
+               }
+               $mergeAttemptResult .= $data;
+       } while ( true );
        pclose( $handle );
 
+       $conflict = $mergeAttemptResult !== '';
+
        # Merge differences
        $cmd = Shell::escape( $wgDiff3, '-a', '-e', '--merge', $mytextName,
                $oldtextName, $yourtextName );
index 5e54b8d..d961e41 100644 (file)
@@ -473,26 +473,46 @@ class GlobalTest extends MediaWikiTestCase {
                ];
        }
 
+       /**
+        * @covers ::wfMerge
+        */
+       public function testMerge_worksWithLessParameters() {
+               $this->markTestSkippedIfNoDiff3();
+
+               $mergedText = null;
+               $successfulMerge = wfMerge( "old1\n\nold2", "old1\n\nnew2", "new1\n\nold2", $mergedText );
+
+               $mergedText = null;
+               $conflictingMerge = wfMerge( 'old', 'old and mine', 'old and yours', $mergedText );
+
+               $this->assertEquals( true, $successfulMerge );
+               $this->assertEquals( false, $conflictingMerge );
+       }
+
        /**
         * @param string $old Text as it was in the database
         * @param string $mine Text submitted while user was editing
         * @param string $yours Text submitted by the user
         * @param bool $expectedMergeResult Whether the merge should be a success
         * @param string $expectedText Text after merge has been completed
+        * @param string $expectedMergeAttemptResult Diff3 output if conflicts occur
         *
         * @dataProvider provideMerge()
         * @group medium
         * @covers ::wfMerge
         */
-       public function testMerge( $old, $mine, $yours, $expectedMergeResult, $expectedText ) {
+       public function testMerge( $old, $mine, $yours, $expectedMergeResult, $expectedText,
+                                                          $expectedMergeAttemptResult ) {
                $this->markTestSkippedIfNoDiff3();
 
                $mergedText = null;
-               $isMerged = wfMerge( $old, $mine, $yours, $mergedText );
+               $attemptMergeResult = null;
+               $isMerged = wfMerge( $old, $mine, $yours, $mergedText, $mergeAttemptResult );
 
                $msg = 'Merge should be a ';
                $msg .= $expectedMergeResult ? 'success' : 'failure';
                $this->assertEquals( $expectedMergeResult, $isMerged, $msg );
+               $this->assertEquals( $expectedMergeAttemptResult, $mergeAttemptResult );
 
                if ( $isMerged ) {
                        // Verify the merged text
@@ -530,6 +550,9 @@ class GlobalTest extends MediaWikiTestCase {
                                "one one one ONE ONE\n" .
                                        "\n" .
                                        "two two TWO TWO\n", // note: will always end in a newline
+
+                               // mergeAttemptResult:
+                               "",
                        ],
 
                        // #1: conflict, fail
@@ -552,6 +575,13 @@ class GlobalTest extends MediaWikiTestCase {
 
                                // result:
                                null,
+
+                               // mergeAttemptResult:
+                               "1,3c\n" .
+                               "one one one\n" .
+                               "\n" .
+                               "two two\n" .
+                               ".\n",
                        ],
                ];
        }