Experimental merging of edit conflicts
authorMr. E23 <e23@users.mediawiki.org>
Sun, 14 Mar 2004 15:05:52 +0000 (15:05 +0000)
committerMr. E23 <e23@users.mediawiki.org>
Sun, 14 Mar 2004 15:05:52 +0000 (15:05 +0000)
includes/DefaultSettings.php
includes/EditPage.php
includes/GlobalFunctions.php

index 11eae78..44ff573 100644 (file)
@@ -210,6 +210,10 @@ $wgDisableAnonTalk = false;
 # Requires zlib support enabled in PHP.
 $wgUseGzip = function_exists( "gzencode" );
 
+# Path to the GNU diff3 utility. If the file doesn't exist,
+# edit conflicts will fall back to the old behaviour (no merging).
+$wgDiff3 = "/usr/bin/diff3";
+
 # We can also compress text in the old revisions table. If this is set on,
 # old revisions will be compressed on page save if zlib support is available.
 # Any compressed revisions will be decompressed on load regardless of this
index f691924..d22df2d 100644 (file)
@@ -170,7 +170,12 @@ class EditPage {
                                # FIXME: This is confusing. In theory we should attempt to merge, finding
                                # the equivalent section if it's unchanged and avoid the conflict.
                                if($isConflict) {
-                                       $this->section = "";
+                                       if( $this->merge() ){
+                                               // Successful merge! Maybe we should tell the user the good news?
+                                               $isConflict = false;
+                                       } else {
+                                               $this->section = "";
+                                       }
                                }
                        }
                        if ( ! $isConflict ) {
@@ -446,6 +451,26 @@ htmlspecialchars( $wgLang->recodeForEdit( $this->textbox1 ) ) .
                        }
                }
        }
+
+       /* private */ function merge(){
+               $oldDate = $this->edittime;
+               $res = wfQuery("SELECT cur_text FROM cur WHERE cur_id=" . 
+                       $this->mTitle->getArticleID() . " FOR UPDATE", DB_WRITE);
+               $obj = wfFetchObject($res);
+
+               $yourtext = $obj->cur_text;
+               $ns = $this->mTitle->getNamespace();
+               $title = wfStrencode( $this->mTitle->getDBkey() );
+               $res = wfQuery("SELECT old_text FROM old WHERE old_namespace = $ns AND ".
+                 "old_title = '{$title}' AND old_timestamp = '{$oldDate}'", DB_WRITE);
+               $obj = wfFetchObject($res);
+               if(wfMerge($obj->old_text, $this->textbox1, $yourtext, $result)){
+                       $this->textbox1 = $result;
+                       return true;
+               } else {
+                       return false;
+               }
+       }
 }
 
 ?>
index e67e778..8133b75 100644 (file)
@@ -849,4 +849,49 @@ function wfPurgeSquidServers ($urlArr) {
        }
        return;
 }
+
+
+# wfMerge attempts to merge differences between three texts. 
+# Returns true for a clean merge and false for failure or a conflict.
+
+function wfMerge( $old, $mine, $yours, &$result ){
+       global $wgDiff3;
+
+       # This check may also protect against code injection in 
+       # case of broken installations.
+       if(! file_exists( $wgDiff3 ) ){ 
+               return false;
+       }
+       $td = "/tmp/";
+       $oldtextFile = fopen( $oldtextName = tempnam( $td, "merge-old-" ), "w" );
+       $mytextFile = fopen( $mytextName = tempnam( $td, "merge-mine-" ), "w" );
+       $yourtextFile = fopen( $yourtextName = tempnam( $td, "merge-your-" ), "w" );
+                       
+       fwrite( $oldtextFile, $old ); fclose( $oldtextFile ); 
+       fwrite( $mytextFile, $mine ); fclose( $mytextFile ); 
+       fwrite( $yourtextFile, $yours ); fclose( $yourtextFile );
+       $cmd = "{$wgDiff3} -a --overlap-only $mytextName $oldtextName $yourtextName";
+       $handle = popen( $cmd, "r" );
+
+       if( fgets( $handle ) ){
+               $conflict = true;
+       } else {
+               $conflict = false;
+       }
+       pclose( $handle );
+       $cmd = "{$wgDiff3} -a --merge $mytextName $oldtextName $yourtextName";
+       $handle = popen( $cmd, "r" );
+       $result = "";
+       do {
+               $data = fread( $handle, 8192 );
+               if ( strlen( $data ) == 0 ) {
+                       break;
+               }
+               $result .= $data;
+       } while ( true );
+       pclose( $handle );
+       unlink( $mytextName ); unlink( $oldtextName ); unlink( $yourtextName );
+       return ! $conflict;
+}
+
 ?>