Skip to content

Commit ac5bea2

Browse files
committed
Do not keep visiting when at max depth
License: MIT Signed-off-by: Hector Sanjuan <[email protected]>
1 parent fa95446 commit ac5bea2

File tree

1 file changed

+48
-19
lines changed

1 file changed

+48
-19
lines changed

core/commands/refs.go

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -262,27 +262,39 @@ func (rw *RefWriter) writeRefsRecursive(n ipld.Node, depth int) (int, error) {
262262
for i, ng := range ipld.GetDAG(rw.Ctx, rw.DAG, n) {
263263
lc := n.Links()[i].Cid
264264
goDeeper, shouldWrite := rw.visit(lc, depth+1) // The children are at depth+1
265-
if shouldWrite {
266-
if err := rw.WriteEdge(nc, lc, n.Links()[i].Name); err != nil {
267-
return count, err
268-
}
269-
}
265+
count++
270266

271-
if !goDeeper {
267+
// Avoid "Get()" on the node. We did a Get on it before
268+
// (we printed it) and must not go deeper. This is an
269+
// optimization for pruned branches.
270+
if !shouldWrite && !goDeeper {
272271
continue
273272
}
274273

274+
// We must write it because it's new, or go deeper. In any case
275+
// we need to make sure this node is fetched and stored.
275276
nd, err := ng.Get(rw.Ctx)
276277
if err != nil {
277278
return count, err
278279
}
279280

280-
c, err := rw.writeRefsRecursive(nd, depth+1)
281-
count += c
282-
if err != nil {
283-
return count, err
281+
// Output this node if we we should
282+
if shouldWrite {
283+
if err := rw.WriteEdge(nc, lc, n.Links()[i].Name); err != nil {
284+
return count, err
285+
}
286+
}
287+
288+
// Keep going deeper if we should
289+
if goDeeper {
290+
c, err := rw.writeRefsRecursive(nd, depth+1)
291+
count += c
292+
if err != nil {
293+
return count, err
294+
}
284295
}
285296
}
297+
286298
return count, nil
287299
}
288300

@@ -292,28 +304,45 @@ func (rw *RefWriter) writeRefsRecursive(n ipld.Node, depth int) (int, error) {
292304
//
293305
// visit will do branch pruning depending on rw.MaxDepth, previously visited
294306
// cids and whether rw.Unique is set. i.e. rw.Unique = false and
295-
// rw.MaxDepth = 1 disables any pruning. But setting rw.Unique to true will
296-
// prune already visited branches.
307+
// rw.MaxDepth = -1 disables any pruning. But setting rw.Unique to true will
308+
// prune already visited branches at the cost of keeping as set of visited
309+
// CIDs in memory.
297310
func (rw *RefWriter) visit(c *cid.Cid, depth int) (bool, bool) {
311+
atMaxDepth := rw.MaxDepth >= 0 && depth == rw.MaxDepth
298312
overMaxDepth := rw.MaxDepth >= 0 && depth > rw.MaxDepth
299313

300-
// The two cases where we can shortcut right away are:
301-
// - When not unique: we print when not overMaxDepth and continue
302-
// in that case
303-
// - When overMaxDepth: we do not continue and do not print
304-
if !rw.Unique || overMaxDepth {
305-
return !overMaxDepth, !overMaxDepth
314+
// Shortcut when we are over max depth. In practice, this
315+
// only applies when calling refs with --maxDepth=0, as root's
316+
// children are already over max depth. Otherwise nothing should
317+
// hit this.
318+
if overMaxDepth {
319+
return false, false
320+
}
321+
322+
// We can shortcut right away if we don't need unique output:
323+
// - we keep traversing when not atMaxDepth
324+
// - always print
325+
if !rw.Unique {
326+
return !atMaxDepth, true
306327
}
307328

308329
// Unique == true from this point.
309330
// Thus, we keep track of seen Cids, and their depth.
310331
if rw.seen == nil {
311332
rw.seen = make(map[string]int)
312333
}
313-
314334
key := string(c.Bytes())
315335
oldDepth, ok := rw.seen[key]
316336

337+
// We can shortcut when atMaxDepth:
338+
// - do not keep traversing
339+
// - print only if not seen before
340+
if atMaxDepth {
341+
return false, !ok
342+
}
343+
344+
// Unique == true && depth < MaxDepth (or unlimited) from this point
345+
317346
// Branch pruning cases:
318347
// - We saw the Cid before and either:
319348
// - Depth is unlimited (MaxDepth = -1)

0 commit comments

Comments
 (0)