Conflicts between deleted blocks were causing false positives, and unnecessary conflict markers in the output.
CHI2WRPHAI5ZDFO4NMUBNMQ5HIHBZBAZD4XV7OUSSZEDDMN4YGSAC
if i == 0 {
continue
}
// We only check for conflicts when the current block is not one that
// has been deleted.
if len(b.DeletedBy) == 0 {
if !reachable[b] {
// If this block is not reachable from the previous block, the order between
// them is undetermined, and therefore we have a conflict.
hasEdge := false
for _, e := range blocks[i-1].Edges {
if e.To == b {
hasEdge = true
break
}
}
if !hasEdge {
// If this block is not a child of the previous block, the order between
// them is undetermined, and therefore we have a conflict.
// The conflict begins just after the closest parent of b.
closestParent := -1
for _, e := range b.ReverseEdges {
parent := index[e.From]
if parent > closestParent {
closestParent = parent
// To find the start of the conflict, we need to look back for the most recent
// block from which b is reachable.
var start int
connected := map[*Block]bool{
b: true,
}
for j := i; j >= 0; j-- {
if j < i && len(blocks[j].DeletedBy) == 0 && connected[blocks[j]] {
start = j + 1
break
}
if connected[blocks[j]] {
for _, e := range blocks[j].ReverseEdges {
connected[e.From] = true
}
}
// The conflict ends just before the closest child of the previous block.
closestChild := len(blocks)
for _, e := range blocks[i-1].Edges {
child := index[e.To]
if child < closestChild {
closestChild = child
// Skip deleted blocks at the start of the conflict.
for len(blocks[start].DeletedBy) > 0 {
start++
// If either side of the conflict consists entirely of deleted vertices,
// it's not really a conflict.
aliveBefore := false
for j := closestParent + 1; j < i; j++ {
if len(blocks[j].DeletedBy) == 0 {
aliveBefore = true
break
// Rather than making a new map of blocks reachable from prev,
// we can reuse our work from the outer loop.
// The reachable map will be replaced at the end of the outer loop anyway.
end := len(blocks)
for j := i + 1; j < len(blocks); j++ {
if len(blocks[j].DeletedBy) == 0 && reachable[blocks[j]] {
end = j
break
}
if reachable[blocks[j]] {
for _, e := range blocks[j].Edges {
reachable[e.To] = true
}
}
}
aliveAfter := false
for j := i; j < closestChild; j++ {
if len(blocks[j].DeletedBy) == 0 {
aliveAfter = true
break
// skip deleted blocks at the end of the conflict.
for len(blocks[end-1].DeletedBy) > 0 {
end--