From 64adca556ea1e41a862eb65c5dcc7019ceeddd06 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Sun, 8 Jun 2025 11:42:50 +0100 Subject: [PATCH] knotserver: git: rework commitsBetween to use rev-list Change-Id: wypzyzpyxkuurpnlsrqqolnrlwrwworw the previous commit iterator approach was faulty in cases of merge commits, as it only uses the first parent returned by .Parents(). this also makes use of the --no-merges flag when preparing commits for format-patch. Signed-off-by: oppiliappan --- knotserver/git/diff.go | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/knotserver/git/diff.go b/knotserver/git/diff.go index 81b6c73..5c1f402 100644 --- a/knotserver/git/diff.go +++ b/knotserver/git/diff.go @@ -205,25 +205,27 @@ func (g *GitRepo) ResolveRevision(revStr string) (*object.Commit, error) { func (g *GitRepo) commitsBetween(newCommit, oldCommit *object.Commit) ([]*object.Commit, error) { var commits []*object.Commit - current := newCommit - for { - if current.Hash == oldCommit.Hash { - break - } - - commits = append(commits, current) + output, err := g.revList( + "--no-merges", // format-patch explicitly prepares only non-merges + fmt.Sprintf("%s..%s", oldCommit.Hash.String(), newCommit.Hash.String()), + ) + if err != nil { + return nil, fmt.Errorf("revlist: %w", err) + } - if len(current.ParentHashes) == 0 { - return nil, fmt.Errorf("old commit %s not found in history of new commit %s", oldCommit.Hash, newCommit.Hash) - } + lines := strings.Split(strings.TrimSpace(string(output)), "\n") + if len(lines) == 1 && lines[0] == "" { + return commits, nil + } - parent, err := current.Parents().Next() + for _, item := range lines { + obj, err := g.r.CommitObject(plumbing.NewHash(item)) if err != nil { - return nil, fmt.Errorf("error getting parent: %w", err) + continue } - current = parent + commits = append(commits, obj) } return commits, nil -- 2.43.0