From 745f02a4820705e02a2c953c2b54dfce7575236f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marius=20D=C3=B6rbandt?= Date: Sun, 17 Nov 2024 23:05:04 +0100 Subject: [PATCH] Fix merging of empty strings Fixes #45. --- ...t.base.ifUnchanged.ifMerged.ifConflict..st | 10 +++--- .../methodProperties.json | 2 +- .../class/diffChunksFrom.to..st | 3 -- .../methodProperties.json | 2 +- .../instance/calculateLcs.st | 32 +++++++++++++++++++ .../methodProperties.json | 5 +++ .../properties.json | 2 ++ 7 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 src/GitS-Core.package/MyersUkkonenDiff.extension/instance/calculateLcs.st create mode 100644 src/GitS-Core.package/MyersUkkonenDiff.extension/methodProperties.json create mode 100644 src/GitS-Core.package/MyersUkkonenDiff.extension/properties.json diff --git a/src/GitS-Core.package/GSMergeUtilities.class/class/stringMergeLeft.right.base.ifUnchanged.ifMerged.ifConflict..st b/src/GitS-Core.package/GSMergeUtilities.class/class/stringMergeLeft.right.base.ifUnchanged.ifMerged.ifConflict..st index bd40fde10..4ed86eeec 100644 --- a/src/GitS-Core.package/GSMergeUtilities.class/class/stringMergeLeft.right.base.ifUnchanged.ifMerged.ifConflict..st +++ b/src/GitS-Core.package/GSMergeUtilities.class/class/stringMergeLeft.right.base.ifUnchanged.ifMerged.ifConflict..st @@ -1,17 +1,17 @@ merging stringMergeLeft: leftString right: rightString base: baseString ifUnchanged: unchangedBlock ifMerged: mergedBlock ifConflict: conflictBlock - | leftLines diffResult | + | leftLines chunks | leftLines := leftString lines. - diffResult := Diff3 new + chunks := (Diff3 new file0: baseString lines; file1: leftLines; file2: rightString lines; diffClass: GSTextUtilities diffClass; - merge: true. - ^ (diffResult size = 1 and: [diffResult first key = #ok]) + yourself) merge: true. + ^ (chunks allSatisfy: [:each | each key = #ok]) ifFalse: [conflictBlock value: (GSMergeConflict left: leftString right: rightString base: baseString)] ifTrue: [ | mergedLines | - mergedLines := diffResult first value. + mergedLines := chunks gather: #value. mergedLines = leftLines ifTrue: [unchangedBlock value] ifFalse: [mergedBlock value: (mergedLines joinSeparatedBy: Character cr)]] \ No newline at end of file diff --git a/src/GitS-Core.package/GSMergeUtilities.class/methodProperties.json b/src/GitS-Core.package/GSMergeUtilities.class/methodProperties.json index 27edbaa8a..b7300f0cb 100644 --- a/src/GitS-Core.package/GSMergeUtilities.class/methodProperties.json +++ b/src/GitS-Core.package/GSMergeUtilities.class/methodProperties.json @@ -3,7 +3,7 @@ "atomicMergeLeft:right:base:ifUnchanged:ifMerged:ifConflict:" : "mad 10/9/2024 16:01", "hexHashMergeFor:left:right:base:ifUnchanged:" : "mad 11/12/2024 15:02", "stringMergeLeft:right:base:ifConflict:" : "mad 10/2/2024 20:57", - "stringMergeLeft:right:base:ifUnchanged:ifMerged:ifConflict:" : "mad 10/9/2024 16:01", + "stringMergeLeft:right:base:ifUnchanged:ifMerged:ifConflict:" : "mad 11/17/2024 23:00", "stringOrNilMergeLeft:right:base:ifUnchanged:ifMerged:ifConflict:" : "mad 10/2/2024 20:56" }, "instance" : { } } diff --git a/src/GitS-Core.package/GSTextUtilities.class/class/diffChunksFrom.to..st b/src/GitS-Core.package/GSTextUtilities.class/class/diffChunksFrom.to..st index 1e0da8f81..2ac04a226 100644 --- a/src/GitS-Core.package/GSTextUtilities.class/class/diffChunksFrom.to..st +++ b/src/GitS-Core.package/GSTextUtilities.class/class/diffChunksFrom.to..st @@ -1,8 +1,5 @@ diffing diffChunksFrom: fromCollection to: toCollection - (fromCollection size = 0 and: [toCollection size = 0]) ifTrue: [ - "MyersUkkonenDiff doesn't properly handle this case" - ^ {#common -> fromCollection}]. ^ self diffClass new file1: fromCollection; file2: toCollection; diff --git a/src/GitS-Core.package/GSTextUtilities.class/methodProperties.json b/src/GitS-Core.package/GSTextUtilities.class/methodProperties.json index 5ef82b950..7aeedde85 100644 --- a/src/GitS-Core.package/GSTextUtilities.class/methodProperties.json +++ b/src/GitS-Core.package/GSTextUtilities.class/methodProperties.json @@ -8,7 +8,7 @@ "asRemovalText:" : "mad 9/10/2023 18:09", "bold:" : "mad 9/27/2023 16:03", "colorText:with:" : "mad 9/10/2023 18:09", - "diffChunksFrom:to:" : "mad 10/4/2024 16:01", + "diffChunksFrom:to:" : "mad 11/17/2024 22:57", "diffClass" : "mad 10/2/2024 18:29", "diffFrom:to:" : "mad 9/20/2023 13:05", "diffFromLines:toLines:" : "mad 9/20/2023 13:05", diff --git a/src/GitS-Core.package/MyersUkkonenDiff.extension/instance/calculateLcs.st b/src/GitS-Core.package/MyersUkkonenDiff.extension/instance/calculateLcs.st new file mode 100644 index 000000000..a5e0c4b59 --- /dev/null +++ b/src/GitS-Core.package/MyersUkkonenDiff.extension/instance/calculateLcs.st @@ -0,0 +1,32 @@ +*GitS-Core-private-override +calculateLcs + "I find one of the longest common subsequences of my the arguments. I assume that none of my arguments are empty. I return nil or an Array which represents a list. The first two elements are the matching line numbers, the last is the next node in the list or nil if there are no more elements. The list containts the longest common subsequence. I'm a modified version of the greedy lcs algorithm from the 6th page of 'An O(ND) Difference Algorithm and Its Variations (1986)' by Eugene W. Myers" + + | n m v lcss max | + n := file1 size. + m := file2 size. + max := m + n. + max = 0 ifTrue: [^ nil]. + v := Array new: 2 * max + 1. + v at: max + 2 put: 0. + lcss := Array new: 2 * max + 1. + 0 to: max do: [ :d | + d negated to: d by: 2 do: [ :k | + | index chain x y | + (k + d = 0 or: [ k ~= d and: [ (v at: max + k ) < (v at: max + k + 2) ] ]) + ifTrue: [ + index := max + k + 2. + x := v at: index ] + ifFalse: [ + index := max + k. + x := (v at: index) + 1 ]. + chain := lcss at: index. + y := x - k. + [ x < n and: [ y < m and: [ (file1 at: x + 1) = (file2 at: y + 1) ] ] ] + whileTrue: [ + chain := { x := x + 1. y := y + 1. chain } ]. + (x >= n and: [ y >= m ]) ifTrue: [ + ^chain ]. + v at: max + k + 1 put: x. + lcss at: max + k + 1 put: chain ] ]. + self error \ No newline at end of file diff --git a/src/GitS-Core.package/MyersUkkonenDiff.extension/methodProperties.json b/src/GitS-Core.package/MyersUkkonenDiff.extension/methodProperties.json new file mode 100644 index 000000000..1e2e0c7dd --- /dev/null +++ b/src/GitS-Core.package/MyersUkkonenDiff.extension/methodProperties.json @@ -0,0 +1,5 @@ +{ + "class" : { + }, + "instance" : { + "calculateLcs" : "mad 11/16/2024 13:52" } } diff --git a/src/GitS-Core.package/MyersUkkonenDiff.extension/properties.json b/src/GitS-Core.package/MyersUkkonenDiff.extension/properties.json new file mode 100644 index 000000000..0c8a8c1e5 --- /dev/null +++ b/src/GitS-Core.package/MyersUkkonenDiff.extension/properties.json @@ -0,0 +1,2 @@ +{ + "name" : "MyersUkkonenDiff" }