From 525092fa9fd6d1552c56303613a5b102b3831561 Mon Sep 17 00:00:00 2001 From: "Mr. E23" Date: Sun, 14 Mar 2004 15:05:52 +0000 Subject: [PATCH] Experimental merging of edit conflicts --- includes/DefaultSettings.php | 4 ++++ includes/EditPage.php | 27 +++++++++++++++++++++- includes/GlobalFunctions.php | 45 ++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 11eae782a5..44ff573b45 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -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 diff --git a/includes/EditPage.php b/includes/EditPage.php index f69192476b..d22df2d5aa 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -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; + } + } } ?> diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index e67e778083..8133b755fa 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -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; +} + ?> -- 2.20.1