package modules import ( "net/http" "gsg/internal/core" "gsg/internal/gitx" ) type Compare struct { Base, Head string // as the user spelled them BaseSHA, HeadSHA string MergeBase string ThreeDot bool Diff gitx.Diff Commits []gitx.Commit // what Head has that Base does not } func init() { core.Register("compare", compareMod) } // compare: diff between two arbitrary commits. // // Ctx.Vars carries the pair, already resolved to SHAs by the server -- so // the ref text never reaches git, same rule as everywhere else. // // "a...b" (three dots) diffs from the merge base, which is what you want // when reviewing a branch: it excludes changes that landed on the base // since the branch forked. "a..b" is the literal endpoint difference. func compareMod(c *core.Ctx, args ...string) (any, error) { base, head := c.Var("baseSHA"), c.Var("headSHA") if base == "" || head == "" { return nil, core.Errorf(http.StatusBadRequest, "compare needs two commits") } cmp := Compare{ Base: c.Var("base"), Head: c.Var("head"), BaseSHA: base, HeadSHA: head, ThreeDot: c.Var("dots") == "3", } from := base if cmp.ThreeDot { mb, err := c.Repo.MergeBase(base, head) if err != nil { return nil, core.Errorf(http.StatusNotFound, "no common ancestor") } cmp.MergeBase, from = mb, mb } d, err := c.Repo.DiffRange(from, head, false) if err != nil && err != gitx.ErrTruncated { return nil, err } cmp.Diff = d if log, err := c.Repo.Log(from+".."+head, 250, 0, false); err == nil { cmp.Commits = log } return cmp, nil }