mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
Add comments explaining how ctySequenceDiff works
The logic behind this code took me a while to understand, so I wrote down what I understand to be the reasoning behind how it works. The trickiest part is rendering changing objects as updates. I think the other pieces are fairly common to LCS sequence diff rendering, so I didn't explain those in detail.
This commit is contained in:
parent
d0d9ee1e62
commit
ef0181cfbd
@ -1814,7 +1814,27 @@ func ctySequenceDiff(old, new []cty.Value) []*plans.Change {
|
||||
lcs := objchange.LongestCommonSubsequence(old, new)
|
||||
var oldI, newI, lcsI int
|
||||
for oldI < len(old) || newI < len(new) || lcsI < len(lcs) {
|
||||
// We first process items in the old and new sequences which are not
|
||||
// equal to the current common sequence item. Old items are marked as
|
||||
// deletions, and new items are marked as additions.
|
||||
//
|
||||
// There is an exception for deleted & created object items, which we
|
||||
// try to render as updates where that makes sense.
|
||||
for oldI < len(old) && (lcsI >= len(lcs) || !old[oldI].RawEquals(lcs[lcsI])) {
|
||||
// Render this as an object update if all of these are true:
|
||||
//
|
||||
// - the current old item is an object;
|
||||
// - there's a current new item which is also an object;
|
||||
// - either there are no common items left, or the current new item
|
||||
// doesn't equal the current common item.
|
||||
//
|
||||
// Why do we need the the last clause? If we have current items in all
|
||||
// three sequences, and the current new item is equal to a common item,
|
||||
// then we should just need to advance the old item list and we'll
|
||||
// eventually find a common item matching both old and new.
|
||||
//
|
||||
// This combination of conditions allows us to render an object update
|
||||
// diff instead of a combination of delete old & create new.
|
||||
isObjectDiff := old[oldI].Type().IsObjectType() && newI < len(new) && new[newI].Type().IsObjectType() && (lcsI >= len(lcs) || !new[newI].RawEquals(lcs[lcsI]))
|
||||
if isObjectDiff {
|
||||
ret = append(ret, &plans.Change{
|
||||
@ -1827,6 +1847,8 @@ func ctySequenceDiff(old, new []cty.Value) []*plans.Change {
|
||||
continue
|
||||
}
|
||||
|
||||
// Otherwise, this item is not part of the common sequence, so
|
||||
// render as a deletion.
|
||||
ret = append(ret, &plans.Change{
|
||||
Action: plans.Delete,
|
||||
Before: old[oldI],
|
||||
@ -1842,6 +1864,9 @@ func ctySequenceDiff(old, new []cty.Value) []*plans.Change {
|
||||
})
|
||||
newI++
|
||||
}
|
||||
|
||||
// When we've exhausted the old & new sequences of items which are not
|
||||
// in the common subsequence, we render a common item and continue.
|
||||
if lcsI < len(lcs) {
|
||||
ret = append(ret, &plans.Change{
|
||||
Action: plans.NoOp,
|
||||
|
Loading…
Reference in New Issue
Block a user