| | $vDiffOld = new VirtualDiffFile( $path, $oldContent ); |
| | $vDiffNew = new VirtualDiffFile( $path, $newContent ); |
| | - |
| | - $isBinary = ($newSha !== '' && $vDiffNew->isBinary()) || |
| | - ($newSha === '' && $oldSha !== '' && $vDiffOld->isBinary()); |
| | + $isBinary = ($newSha !== '' && $vDiffNew->isBinary()) || |
| | + ($newSha === '' && $oldSha !== '' && $vDiffOld->isBinary()); |
| | |
| | $result = [ |
 |
| | $oldLines = explode( "\n", str_replace( "\r\n", "\n", $old ) ); |
| | $newLines = explode( "\n", str_replace( "\r\n", "\n", $new ) ); |
| | - |
| | - unset( $old, $new ); |
| | - |
| | - $m = count( $oldLines ); |
| | - $n = count( $newLines ); |
| | - $start = 0; |
| | - $end = 0; |
| | + $m = count( $oldLines ); |
| | + $n = count( $newLines ); |
| | + $start = 0; |
| | + $end = 0; |
| | |
| | while( $start < $m && $start < $n && |
 |
| | $oldSlice = array_slice( $oldLines, $start, $m - $start - $end ); |
| | $newSlice = array_slice( $newLines, $start, $n - $start - $end ); |
| | - $result = []; |
| | - |
| | - unset( $oldLines, $newLines ); |
| | - |
| | $countOld = count( $oldSlice ); |
| | $countNew = count( $newSlice ); |
| | $limit = 100000; |
| | + $result = []; |
| | |
| | - if( ( $countOld * $countNew ) > $limit ) { |
| | - error_log( "Diff complexity too high: $countOld * $countNew > $limit" ); |
| | - $result = [[ 't' => 'gap' ]]; |
| | + if( ($countOld * $countNew) > $limit ) { |
| | + $result = $this->buildFallbackDiff( $oldSlice, $newSlice, $start ); |
| | } else { |
| | $ops = $this->computeLCS( $oldSlice, $newSlice ); |
| | - $stream = $this->buildDiffStream( |
| | - $ops, |
| | - $oldSlice, |
| | - $start, |
| | - $m, |
| | - $end |
| | - ); |
| | + $stream = $this->buildDiffStream( $ops, $start ); |
| | $result = $this->formatDiffOutput( $stream ); |
| | } |
| | |
| | return $result; |
| | } |
| | |
| | - private function buildDiffStream( |
| | - array $ops, |
| | - array $oldSlice, |
| | - int $start, |
| | - int $m, |
| | - int $end |
| | + private function buildFallbackDiff( |
| | + array $old, |
| | + array $new, |
| | + int $offset |
| | ): array { |
| | + $stream = []; |
| | + $currO = $offset + 1; |
| | + $currN = $offset + 1; |
| | + |
| | + foreach( $old as $line ) { |
| | + $stream[] = [ 't' => '-', 'l' => $line, 'no' => $currO++, 'nn' => null ]; |
| | + } |
| | + |
| | + foreach( $new as $line ) { |
| | + $stream[] = [ 't' => '+', 'l' => $line, 'no' => null, 'nn' => $currN++ ]; |
| | + } |
| | + |
| | + return $stream; |
| | + } |
| | + |
| | + private function buildDiffStream( array $ops, int $start ): array { |
| | $stream = []; |
| | $currO = $start + 1; |
| | $currN = $start + 1; |
| | |
| | foreach( $ops as $op ) { |
| | - if( $op['t'] === ' ' ) { |
| | - $stream[] = [ |
| | - 't' => ' ', 'l' => $op['l'], 'no' => $currO++, 'nn' => $currN++ |
| | - ]; |
| | - } elseif( $op['t'] === '-' ) { |
| | - $stream[] = [ |
| | - 't' => '-', 'l' => $op['l'], 'no' => $currO++, 'nn' => null |
| | - ]; |
| | - } elseif( $op['t'] === '+' ) { |
| | - $stream[] = [ |
| | - 't' => '+', 'l' => $op['l'], 'no' => null, 'nn' => $currN++ |
| | - ]; |
| | - } |
| | + $stream[] = [ |
| | + 't' => $op['t'], |
| | + 'l' => $op['l'], |
| | + 'no' => $op['t'] === '+' ? null : $currO++, |
| | + 'nn' => $op['t'] === '-' ? null : $currN++ |
| | + ]; |
| | } |
| | |
 |
| | for( $i = 0; $i < $n; $i++ ) { |
| | if( $stream[$i]['t'] !== ' ' ) { |
| | - $start = max( 0, $i - $context ); |
| | - $end = min( $n - 1, $i + $context ); |
| | + $low = max( 0, $i - $context ); |
| | + $high = min( $n - 1, $i + $context ); |
| | |
| | - for( $j = $start; $j <= $end; $j++ ) { |
| | + for( $j = $low; $j <= $high; $j++ ) { |
| | $keep[$j] = true; |
| | } |
 |
| | $i--; |
| | $j--; |
| | - } elseif( $j > 0 && |
| | - ($i === 0 || $c[$i][$j - 1] >= $c[$i - 1][$j]) ) { |
| | + } elseif( $j > 0 && ($i === 0 || $c[$i][$j - 1] >= $c[$i - 1][$j]) ) { |
| | $diff[] = [ 't' => '+', 'l' => $new[$j - 1] ]; |
| | $j--; |
| | } elseif( $i > 0 && ($j === 0 || $c[$i][$j - 1] < $c[$i - 1][$j]) ) { |
| | $diff[] = [ 't' => '-', 'l' => $old[$i - 1] ]; |
| | $i--; |
| | } |
| | } |
| | |
| | return array_reverse( $diff ); |
| | - } |
| | -} |
| | - |
| | -class VirtualDiffFile extends File { |
| | - public function __construct( string $name, string $content ) { |
| | - parent::__construct( |
| | - $name, |
| | - '', |
| | - '100644', |
| | - 0, |
| | - strlen( $content ), |
| | - $content |
| | - ); |
| | } |
| | } |