Repository: dolthub/dolt
File: go/libraries/doltcore/doltdb/commit_itr.go (Go)

Code before:
// CommitItrForRoots will return a CommitItr which will iterate over all ancestor commits of the provided rootCommits.
func CommitItrForRoots[C Context](ddb *DoltDB, rootCommits ...*Commit) CommitItr[C] {
	return &commitItr[C]{
		ddb:         ddb,
		rootCommits: rootCommits,
		added:       make(map[hash.Hash]bool, 4096),
		unprocessed: make([]hash.Hash, 0, 4096),
	}
}

func (cmItr *commitItr[C]) Reset(ctx context.Context) error {
	cmItr.curr = nil
	cmItr.currentRoot = 0
	cmItr.added = make(map[hash.Hash]bool, 4096)
	cmItr.unprocessed = cmItr.unprocessed[:0]

	return nil
}

// Next returns the hash of the next commit, and a pointer to that commit.  It handles making sure the list of commits
// returned are unique.  When complete Next will return hash.Hash{}, nil, io.EOF
func (cmItr *commitItr[C]) Next(ctx C) (hash.Hash, *OptionalCommit, *datas.CommitMeta, uint64, error) {
	for cmItr.curr == nil {
		if cmItr.currentRoot >= len(cmItr.rootCommits) {
			return hash.Hash{}, nil, nil, 0, io.EOF
		}

		cm := cmItr.rootCommits[cmItr.currentRoot]
		h, err := cm.HashOf()

		if err != nil {
			return hash.Hash{}, nil, nil, 0, err
		}

		if !cmItr.added[h] {
			cmItr.added[h] = true
			cmItr.curr = cm
			return h, &OptionalCommit{cmItr.curr, h}, nil, 0, nil
		}

		cmItr.currentRoot++
	}

	parents, err := cmItr.curr.ParentHashes(ctx)

	if err != nil {
		return hash.Hash{}, nil, nil, 0, err
	}

	for _, h := range parents {
		if !cmItr.added[h] {

Review comment (suggestion):
Looks like this `Next()` implementation will never actually return a `*CommitMeta` instance, right? That makes this interface a little bit tricky/frustrating to use when the caller doesn't know which implementations return which fields. At minimum, it's worth documenting this better, perhaps in the main interface definition (to document that some implementations may not return CommitMeta and callers should always test for nil before using that param) and perhaps also in the implementations that don't return `CommitMeta` data since they are not really fully implementing the interface's contract. 

Code after:
}

// CommitItrForRoots will return a CommitItr which will iterate over all ancestor commits of the provided rootCommits.
func CommitItrForRoots[C Context](ddb *DoltDB, rootCommits ...*Commit) CommitItr[C] {
	return &commitItr[C]{
		ddb:         ddb,
		rootCommits: rootCommits,
		added:       make(map[hash.Hash]bool, 4096),
		unprocessed: make([]hash.Hash, 0, 4096),
	}
}

func (cmItr *commitItr[C]) Reset(ctx context.Context) error {
	cmItr.curr = nil
	cmItr.currentRoot = 0
	cmItr.added = make(map[hash.Hash]bool, 4096)
	cmItr.unprocessed = cmItr.unprocessed[:0]

	return nil
}

// Next returns the hash of the next commit, and a pointer to that commit.
// It handles making sure the list of commits returned are unique.
// When complete Next will return hash.Hash{}, nil, nil, 0, io.EOF.
// Note: This implementation always returns nil for the metadata and height return values.
func (cmItr *commitItr[C]) Next(ctx C) (hash.Hash, *OptionalCommit, *datas.CommitMeta, uint64, error) {
	for cmItr.curr == nil {
		if cmItr.currentRoot >= len(cmItr.rootCommits) {
			return hash.Hash{}, nil, nil, 0, io.EOF
		}

		cm := cmItr.rootCommits[cmItr.currentRoot]
		h, err := cm.HashOf()

		if err != nil {
			return hash.Hash{}, nil, nil, 0, err
		}

		if !cmItr.added[h] {
			cmItr.added[h] = true
			cmItr.curr = cm
			return h, &OptionalCommit{cmItr.curr, h}, nil, 0, nil
		}

		cmItr.currentRoot++
	}

	parents, err := cmItr.curr.ParentHashes(ctx)

	if err != nil {
		return hash.Hash{}, nil, nil, 0, err