Skip to content

Commit 7741f9f

Browse files
committed
fix(model-client): endless merge in VersionMerger
model-server and model-client were both doing the same merge creating two new versions that were merged again into another version. Both sides were creating new merges forever without any actual changes to the model.
1 parent fd663d2 commit 7741f9f

File tree

1 file changed

+21
-0
lines changed

1 file changed

+21
-0
lines changed

model-datastructure/src/commonMain/kotlin/org/modelix/model/VersionMerger.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,32 @@ class VersionMerger(private val storeCache: IDeserializingKeyValueStore, private
4545
}
4646
}
4747

48+
private fun collectLatestNonMerges(version: CLVersion?, visited: MutableSet<String>, result: MutableSet<Long>) {
49+
if (version == null) return
50+
if (!visited.add(version.getContentHash())) return
51+
if (version.isMerge()) {
52+
collectLatestNonMerges(version.getMergedVersion1(), visited, result)
53+
collectLatestNonMerges(version.getMergedVersion2(), visited, result)
54+
} else {
55+
result.add(version.id)
56+
collectLatestNonMerges(version.baseVersion, visited, result)
57+
}
58+
}
59+
4860
protected fun mergeHistory(leftVersion: CLVersion, rightVersion: CLVersion): CLVersion {
4961
if (leftVersion.hash == rightVersion.hash) return leftVersion
5062
val commonBase = Companion.commonBaseVersion(leftVersion, rightVersion)
5163
if (commonBase?.hash == leftVersion.hash) return rightVersion
5264
if (commonBase?.hash == rightVersion.hash) return leftVersion
65+
66+
val leftNonMerges = HashSet<Long>().also { collectLatestNonMerges(leftVersion, HashSet(), it) }
67+
val rightNonMerges = HashSet<Long>().also { collectLatestNonMerges(rightVersion, HashSet(), it) }
68+
if (leftNonMerges == rightNonMerges) {
69+
// If there is no actual change on both sides, but they just did the same merge, we have to pick one
70+
// of them, otherwise both sides will continue creating merges forever.
71+
return if (leftVersion.id < rightVersion.id) leftVersion else rightVersion
72+
}
73+
5374
val versionsToApply = LinearHistory(commonBase?.hash).load(leftVersion, rightVersion)
5475

5576
// println("merge ${getVersion(leftVersionHash).id.toString(16)} ${LinearHistory(storeCache, commonBase).load(leftVersion).map { it.id.toString(16) }} and ${getVersion(rightVersionHash).id.toString(16)} ${LinearHistory(storeCache, commonBase).load(rightVersion).map { it.id.toString(16) }}: ${commonBase?.let{getVersion(it)}?.id?.toString(16)} + ${versionsToApply.map { it.id.toString(16) }}")

0 commit comments

Comments
 (0)