knotserver: git: rework commitsBetween to use rev-list #230

merged
opened by oppi.li targeting master from push-ovrqrxnpvroz

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 me@oppi.li

Changed files
+15 -13
knotserver
git
+15 -13
knotserver/git/diff.go
···
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