{"contents":"package git\n\nimport (\n\t\"github.com/go-git/go-git/v5/plumbing\"\n\t\"github.com/go-git/go-git/v5/plumbing/object\"\n\t\"github.com/go-git/go-git/v5/utils/merkletrie\"\n)\n\n// DiffEntry represents a changed file between two commits.\ntype DiffEntry struct {\n\tName string `json:\"name\"`\n\tAction string `json:\"action\"` // \"add\", \"delete\", \"modify\"\n}\n\n// Diff returns the file changes between two commits.\nfunc (repo *Repo) Diff(oldHash, newHash plumbing.Hash) ([]DiffEntry, error) {\n\toldCommit, err := repo.r.CommitObject(oldHash)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnewCommit, err := repo.r.CommitObject(newHash)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\toldTree, err := oldCommit.Tree()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tnewTree, err := newCommit.Tree()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tchanges, err := oldTree.Diff(newTree)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar entries []DiffEntry\n\tfor _, c := range changes {\n\t\tentry := DiffEntry{Name: changeName(c)}\n\n\t\taction, err := c.Action()\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tswitch action {\n\t\tcase merkletrie.Insert:\n\t\t\tentry.Action = \"add\"\n\t\tcase merkletrie.Delete:\n\t\t\tentry.Action = \"delete\"\n\t\tdefault:\n\t\t\tentry.Action = \"modify\"\n\t\t}\n\t\tentries = append(entries, entry)\n\t}\n\n\treturn entries, nil\n}\n\n// Patch returns a unified diff patch between two commits.\nfunc (repo *Repo) Patch(oldHash, newHash plumbing.Hash) (string, error) {\n\toldCommit, err := repo.r.CommitObject(oldHash)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tnewCommit, err := repo.r.CommitObject(newHash)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\tpatch, err := oldCommit.Patch(newCommit)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\n\treturn patch.String(), nil\n}\n\nfunc changeName(c *object.Change) string {\n\tif c.To.Name != \"\" {\n\t\treturn c.To.Name\n\t}\n\treturn c.From.Name\n}\n","path":"git/diff.go","ref":"main"}