some fixes in merge3

This commit is contained in:
Sergey Chernov 2023-03-21 05:27:24 +01:00
parent 2262c66b63
commit 08ce64796b
4 changed files with 41 additions and 23 deletions

View File

@ -1,13 +1,14 @@
plugins { plugins {
kotlin("multiplatform") version "1.8.0" kotlin("multiplatform") version "1.7.21"
`maven-publish` `maven-publish`
} }
group = "net.sergeych" group = "net.sergeych"
version = "0.0.1-SNAPSHOT" version = "0.0.3-SNAPSHOT"
repositories { repositories {
mavenCentral() mavenCentral()
mavenLocal()
maven("https://maven.universablockchain.com") maven("https://maven.universablockchain.com")
} }
@ -43,7 +44,6 @@ kotlin {
dependencies { dependencies {
implementation("dev.gitlive:kotlin-diff-utils:4.1.4") implementation("dev.gitlive:kotlin-diff-utils:4.1.4")
implementation("net.sergeych:mp_stools:[1.3.3,)") implementation("net.sergeych:mp_stools:[1.3.3,)")
} }
} }
val commonTest by getting { val commonTest by getting {

View File

@ -281,7 +281,7 @@ acorn-import-assertions@^1.7.6:
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==
acorn@^8.5.0, acorn@^8.7.1: acorn@^8.4.1, acorn@^8.5.0:
version "8.8.2" version "8.8.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
@ -652,7 +652,7 @@ engine.io@~6.4.1:
engine.io-parser "~5.0.3" engine.io-parser "~5.0.3"
ws "~8.11.0" ws "~8.11.0"
enhanced-resolve@^5.10.0: enhanced-resolve@^5.9.3:
version "5.12.0" version "5.12.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634"
integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==
@ -1781,7 +1781,7 @@ void-elements@^2.0.0:
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==
watchpack@^2.4.0: watchpack@^2.3.1:
version "2.4.0" version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
@ -1827,21 +1827,21 @@ webpack-sources@^3.2.3:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
webpack@5.74.0: webpack@5.73.0:
version "5.74.0" version "5.73.0"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.73.0.tgz#bbd17738f8a53ee5760ea2f59dce7f3431d35d38"
integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==
dependencies: dependencies:
"@types/eslint-scope" "^3.7.3" "@types/eslint-scope" "^3.7.3"
"@types/estree" "^0.0.51" "@types/estree" "^0.0.51"
"@webassemblyjs/ast" "1.11.1" "@webassemblyjs/ast" "1.11.1"
"@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1"
"@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1"
acorn "^8.7.1" acorn "^8.4.1"
acorn-import-assertions "^1.7.6" acorn-import-assertions "^1.7.6"
browserslist "^4.14.5" browserslist "^4.14.5"
chrome-trace-event "^1.0.2" chrome-trace-event "^1.0.2"
enhanced-resolve "^5.10.0" enhanced-resolve "^5.9.3"
es-module-lexer "^0.9.0" es-module-lexer "^0.9.0"
eslint-scope "5.1.1" eslint-scope "5.1.1"
events "^3.2.0" events "^3.2.0"
@ -1854,7 +1854,7 @@ webpack@5.74.0:
schema-utils "^3.1.0" schema-utils "^3.1.0"
tapable "^2.1.1" tapable "^2.1.1"
terser-webpack-plugin "^5.1.3" terser-webpack-plugin "^5.1.3"
watchpack "^2.4.0" watchpack "^2.3.1"
webpack-sources "^3.2.3" webpack-sources "^3.2.3"
which@^1.2.1: which@^1.2.1:

View File

@ -5,9 +5,6 @@ import dev.gitlive.difflib.patch.AbstractDelta
import dev.gitlive.difflib.patch.ChangeDelta import dev.gitlive.difflib.patch.ChangeDelta
import dev.gitlive.difflib.patch.DeleteDelta import dev.gitlive.difflib.patch.DeleteDelta
import dev.gitlive.difflib.patch.InsertDelta import dev.gitlive.difflib.patch.InsertDelta
import net.sergeych.mp_logger.Log
import net.sergeych.mp_logger.LogTag
import net.sergeych.mp_logger.debug
import net.sergeych.sprintf.sprintf import net.sergeych.sprintf.sprintf
/** /**
@ -77,14 +74,18 @@ sealed class MergedBlock<T> {
/** /**
* Perform 3-way merge. See [merge3] for details. * Perform 3-way merge. See [merge3] for details.
*/ */
private class Merge3<T>(val source: List<T>, val variantA: List<T>, val variantB: List<T>) : private class Merge3<T>(val source: List<T>, val variantA: List<T>, val variantB: List<T>,
LogTag("MRG3", Log.Level.INFO) { val showDebug: Boolean = false) {
private val reindex = source.indices.toMutableList() private val reindex = source.indices.toMutableList()
private val changeCount = MutableList(source.size) { 0 } private val changeCount = MutableList(source.size) { 0 }
val result = source.toMutableList() val result = source.toMutableList()
private fun debug( f: ()-> String ) {
if( showDebug ) println(f())
}
private fun trace() { private fun trace() {
debug { result.indices.joinToString("") { "%3d".sprintf(it) } } debug { result.indices.joinToString("") { "%3d".sprintf(it) } }
@ -139,15 +140,20 @@ private class Merge3<T>(val source: List<T>, val variantA: List<T>, val variantB
debug { "deleting $count elements @$sourcePosition" } debug { "deleting $count elements @$sourcePosition" }
val position = findPosition(sourcePosition) val position = findPosition(sourcePosition)
var sp = sourcePosition var sp = sourcePosition
// how much to shoft reindex, depends on actual deletions count:
var shift = count
for (i in position until position + count) { for (i in position until position + count) {
// it this position is already removed, do nothing // it this position is already removed, do nothing
if (reindex[sp] < 0) continue if (reindex[sp] < 0) {
shift--
continue
}
reindex[sp++] = -1 reindex[sp++] = -1
result.removeAt(position) result.removeAt(position)
changeCount.removeAt(position) changeCount.removeAt(position)
} }
while (sp < reindex.size) { while (sp < reindex.size) {
reindex[sp].let { if (it > 0) reindex[sp] = it - count } reindex[sp].let { if (it > 0) reindex[sp] = it - shift }
sp++ sp++
} }
} }
@ -257,6 +263,4 @@ private class Merge3<T>(val source: List<T>, val variantA: List<T>, val variantB
* See [MergeResult] for interpreting results * See [MergeResult] for interpreting results
*/ */
fun <T> merge3(source: List<T>, a: List<T>, b: List<T>, showDebug: Boolean = false): MergeResult<T> = fun <T> merge3(source: List<T>, a: List<T>, b: List<T>, showDebug: Boolean = false): MergeResult<T> =
Merge3(source, a, b).also { Merge3(source, a, b, showDebug).perform()
if (showDebug) it.logLevel = Log.Level.DEBUG
}.perform()

View File

@ -19,6 +19,20 @@ class BasicTest {
assertEquals("Bye cruel world!!!", m.merged.str) assertEquals("Bye cruel world!!!", m.merged.str)
// assertTrue(m.noConflicts) // assertTrue(m.noConflicts)
} }
@Test
fun testMergeNoConflicts3() {
Log.connectConsole()
val src = "1Hello, world!".toList()
val a = "Hello, friend!".toList()
val b = "Bye world!".toList()
val m = merge3(src, a, b, true)
println(m.merged.str)
// println(m.conflicts)
println(m.changedAreas)
assertEquals("Bye friend!", m.merged.str)
// assertTrue(m.noConflicts)
}
@Test @Test
fun testMergeNoConflicts2() { fun testMergeNoConflicts2() {