Few more changes and tree fixes

This commit is contained in:
mcrakhman 2022-09-09 09:45:25 +02:00 committed by Mikhail Iudin
parent b1c6c7e44e
commit 2d00719a05
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
2 changed files with 28 additions and 12 deletions

View File

@ -106,11 +106,14 @@ func (t *Tree) Add(changes ...*Change) (mode Mode) {
return Rebuild return Rebuild
} }
// beforeHeadsIds is definitely not empty, because the tree is not empty
stack := make([]*Change, len(beforeHeadIds), len(beforeHeadIds)) stack := make([]*Change, len(beforeHeadIds), len(beforeHeadIds))
for i, hid := range beforeHeadIds { for i, hid := range beforeHeadIds {
stack[i] = t.attached[hid] stack[i] = t.attached[hid]
} }
// mode is Append for cases when we can safely start iterating
// from old heads to append the state
mode = Append mode = Append
t.dfsNext(stack, t.dfsNext(stack,
func(_ *Change) (isContinue bool) { func(_ *Change) (isContinue bool) {
@ -119,6 +122,12 @@ func (t *Tree) Add(changes ...*Change) (mode Mode) {
func(_ []*Change) { func(_ []*Change) {
// checking if some new changes were not visited // checking if some new changes were not visited
for _, ch := range changes { for _, ch := range changes {
// if the change was not added, then skipping
if _, ok := t.attached[ch.Id]; !ok {
continue
}
// if some new change was not visited,
// then we can't start from old heads, we need to start from root, so Rebuild
if !ch.visited { if !ch.visited {
mode = Rebuild mode = Rebuild
break break
@ -297,7 +306,9 @@ func (t *Tree) dfsPrev(stack []*Change, breakpoints []string, visit func(ch *Cha
} }
defer func() { defer func() {
afterVisit(t.visitedBuf) if afterVisit != nil {
afterVisit(t.visitedBuf)
}
for _, ch := range t.visitedBuf { for _, ch := range t.visitedBuf {
ch.visited = false ch.visited = false
} }
@ -329,7 +340,9 @@ func (t *Tree) dfsNext(stack []*Change, visit func(ch *Change) (isContinue bool)
t.visitedBuf = t.visitedBuf[:0] t.visitedBuf = t.visitedBuf[:0]
defer func() { defer func() {
afterVisit(t.visitedBuf) if afterVisit != nil {
afterVisit(t.visitedBuf)
}
for _, ch := range t.visitedBuf { for _, ch := range t.visitedBuf {
ch.visited = false ch.visited = false
} }
@ -358,12 +371,15 @@ func (t *Tree) dfsNext(stack []*Change, visit func(ch *Change) (isContinue bool)
func (t *Tree) updateHeads() { func (t *Tree) updateHeads() {
var newHeadIds []string var newHeadIds []string
t.iterate(t.root, func(c *Change) (isContinue bool) { t.dfsNext(
if len(c.Next) == 0 { []*Change{t.root},
newHeadIds = append(newHeadIds, c.Id) func(ch *Change) (isContinue bool) {
} if len(ch.Next) == 0 {
return true newHeadIds = append(newHeadIds, ch.Id)
}) }
return true
},
nil)
t.headIds = newHeadIds t.headIds = newHeadIds
sort.Strings(t.headIds) sort.Strings(t.headIds)
} }

View File

@ -46,20 +46,20 @@ func (i *iterator) topSort(start *Change) {
ch := stack[len(stack)-1] ch := stack[len(stack)-1]
stack = stack[:len(stack)-1] stack = stack[:len(stack)-1]
// this looks a bit clumsy, but the idea is that we will go through the change again as soon as we finished // here we visit the change second time to add it to results
// going through its branches // all next changes at this point were visited
if ch.branchesFinished { if ch.branchesFinished {
i.resBuf = append(i.resBuf, ch) i.resBuf = append(i.resBuf, ch)
ch.branchesFinished = false ch.branchesFinished = false
continue continue
} }
// in theory, it may be the case that we add the change two times
// but probably due to the way how we build the tree, we won't need it
if ch.visited { if ch.visited {
continue continue
} }
// put the change again into stack, so we can add it to results
// after all the next changes
stack = append(stack, ch) stack = append(stack, ch)
ch.visited = true ch.visited = true
ch.branchesFinished = true ch.branchesFinished = true