Skip to content

Commit 1b03756

Browse files
committed
history_idx: do not visit a parent more than once
There are cases where it can enter a cycle Signed-off-by: Javi Fontan <[email protected]>
1 parent bac7d17 commit 1b03756

File tree

1 file changed

+19
-2
lines changed

1 file changed

+19
-2
lines changed

internal/function/history_idx.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ func (f *HistoryIdx) repoHistoryIdx(repo *git.Repository, start, target plumbing
125125
// history. Because the frame keeps track of which was its index, we can
126126
// return accurate indexes even if there are multiple branches.
127127
stack := []*stackFrame{{0, 0, []plumbing.Hash{start}}}
128+
visitedHashes := make(map[plumbing.Hash]struct{})
128129

129130
for {
130131
if len(stack) == 0 {
@@ -133,7 +134,13 @@ func (f *HistoryIdx) repoHistoryIdx(repo *git.Repository, start, target plumbing
133134

134135
frame := stack[len(stack)-1]
135136

136-
c, err := repo.CommitObject(frame.hashes[frame.pos])
137+
h := frame.hashes[frame.pos]
138+
_, ok := visitedHashes[h]
139+
if !ok {
140+
visitedHashes[h] = struct{}{}
141+
}
142+
143+
c, err := repo.CommitObject(h)
137144
if err == plumbing.ErrObjectNotFound {
138145
return -1, nil
139146
}
@@ -153,7 +160,17 @@ func (f *HistoryIdx) repoHistoryIdx(repo *git.Repository, start, target plumbing
153160
}
154161

155162
if c.NumParents() > 0 {
156-
stack = append(stack, &stackFrame{frame.idx + 1, 0, c.ParentHashes})
163+
newParents := make([]plumbing.Hash, 0, c.NumParents())
164+
for _, h = range c.ParentHashes {
165+
_, ok = visitedHashes[h]
166+
if !ok {
167+
newParents = append(newParents, h)
168+
}
169+
}
170+
171+
if len(newParents) > 0 {
172+
stack = append(stack, &stackFrame{frame.idx + 1, 0, newParents})
173+
}
157174
}
158175
}
159176
}

0 commit comments

Comments
 (0)