More accurate conflict detection
Dependencies
- [2]
4JR6O4JTTry a new approach to deletion - [3]
Z6CD2LYKAdd tijo-conflicts command - [4]
AYLFNM5CAdd the ability to output the contents of a file.
Change contents
- edit in output.go at line 56
// prev is the most recent non-deleted block.var prev *Block// reachable is the set of blocks that are reachable from prev.reachable := map[*Block]bool{blocks[0]: true,} - replacement in output.go at line 66
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. - replacement in output.go at line 73
hasEdge := falsefor _, e := range blocks[i-1].Edges {if e.To == b {hasEdge = truebreak}}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 := -1for _, 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 intconnected := map[*Block]bool{b: true,}for j := i; j >= 0; j-- {if j < i && len(blocks[j].DeletedBy) == 0 && connected[blocks[j]] {start = j + 1break}if connected[blocks[j]] {for _, e := range blocks[j].ReverseEdges {connected[e.From] = true}} - edit in output.go at line 90
} - replacement in output.go at line 91
// 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++ - edit in output.go at line 95
} - replacement in output.go at line 96[4.2099]→[4.2099:2277](∅→∅),[4.2277]→[2.1254:1293](∅→∅),[2.1293]→[4.2298:2333](∅→∅),[4.2298]→[4.2298:2333](∅→∅)
// If either side of the conflict consists entirely of deleted vertices,// it's not really a conflict.aliveBefore := falsefor j := closestParent + 1; j < i; j++ {if len(blocks[j].DeletedBy) == 0 {aliveBefore = truebreak// 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 = jbreak}if reachable[blocks[j]] {for _, e := range blocks[j].Edges {reachable[e.To] = true}} - replacement in output.go at line 112[4.2339]→[4.2339:2406](∅→∅),[4.2406]→[2.1294:1333](∅→∅),[2.1333]→[4.2427:2461](∅→∅),[4.2427]→[4.2427:2461](∅→∅)
}aliveAfter := falsefor j := i; j < closestChild; j++ {if len(blocks[j].DeletedBy) == 0 {aliveAfter = truebreak// skip deleted blocks at the end of the conflict.for len(blocks[end-1].DeletedBy) > 0 {end-- - edit in output.go at line 117
} - edit in output.go at line 118
if aliveBefore && aliveAfter { - replacement in output.go at line 119
Start: closestParent + 1,Start: start, - replacement in output.go at line 121
End: closestChild,End: end, - edit in output.go at line 124
prev = breachable = map[*Block]bool{prev: true,} - edit in output.go at line 130
if reachable[b] {for _, e := range b.Edges {reachable[e.To] = true}}