package commit_test
import (
"bytes"
"strings"
"testing"
"lindenii.org/go/furgit/internal/testgit"
"lindenii.org/go/furgit/object/commit"
"lindenii.org/go/furgit/object/id"
"lindenii.org/go/furgit/object/typ"
)
func TestParse(t *testing.T) {
t.Parallel()
commitTreeOptions := func(message string) testgit.CommitTreeOptions {
return testgit.CommitTreeOptions{
Message: message,
Author: testgit.Identity{
Name: "Test Author",
Email: "author@example.org",
},
Committer: testgit.Identity{
Name: "Test Committer",
Email: "committer@example.org",
},
AuthorDate: "1234567890 -0730",
CommitterDate: "1234567999 +0545",
}
}
for _, objectFormat := range id.SupportedObjectFormats() {
t.Run(objectFormat.String(), func(t *testing.T) {
t.Parallel()
repo, err := testgit.NewRepo(t, testgit.RepoOptions{ObjectFormat: objectFormat})
if err != nil {
t.Fatalf("NewRepo: %v", err)
}
blobID, err := repo.HashObject(t, typ.TypeBlob, strings.NewReader("content\n"))
if err != nil {
t.Fatalf("HashObject: %v", err)
}
treeID, err := repo.MkTree(t, []testgit.TreeEntry{
{Mode: "100644", Type: typ.TypeBlob, OID: blobID, Name: "file.txt"},
})
if err != nil {
t.Fatalf("MkTree: %v", err)
}
rootID, err := repo.CommitTree(t, treeID, commitTreeOptions("root subject\n\nroot body"))
if err != nil {
t.Fatalf("CommitTree(root): %v", err)
}
childID, err := repo.CommitTree(t, treeID, commitTreeOptions("child subject\n\nchild body"), rootID)
if err != nil {
t.Fatalf("CommitTree(child): %v", err)
}
sideID, err := repo.CommitTree(t, treeID, commitTreeOptions("side subject\n\nside body"))
if err != nil {
t.Fatalf("CommitTree(side): %v", err)
}
mergeID, err := repo.CommitTree(t, treeID, commitTreeOptions("merge subject\n\nmerge body"), childID, sideID)
if err != nil {
t.Fatalf("CommitTree(merge): %v", err)
}
for _, tc := range []struct {
name string
oid id.ObjectID
parents []id.ObjectID
message []byte
}{
{
name: "root",
oid: rootID,
message: []byte("root subject\n\nroot body\n"),
},
{
name: "child",
oid: childID,
parents: []id.ObjectID{rootID},
message: []byte("child subject\n\nchild body\n"),
},
{
name: "merge",
oid: mergeID,
parents: []id.ObjectID{childID, sideID},
message: []byte("merge subject\n\nmerge body\n"),
},
} {
t.Run(tc.name, func(t *testing.T) {
rawBody, err := repo.CatFile(t, typ.TypeCommit, tc.oid)
if err != nil {
t.Fatalf("CatFile: %v", err)
}
parsed, err := commit.Parse(rawBody, objectFormat)
if err != nil {
t.Fatalf("Parse: %v", err)
}
if parsed.Tree != treeID {
t.Fatalf("tree id mismatch: got %s want %s", parsed.Tree, treeID)
}
if len(parsed.Parents) != len(tc.parents) {
t.Fatalf("parent count = %d, want %d", len(parsed.Parents), len(tc.parents))
}
for i, parent := range tc.parents {
if parsed.Parents[i] != parent {
t.Fatalf("parent[%d] = %s, want %s", i, parsed.Parents[i], parent)
}
}
if !bytes.Equal(parsed.Author.Name, []byte("Test Author")) {
t.Fatalf("author name = %q, want %q", parsed.Author.Name, "Test Author")
}
if !bytes.Equal(parsed.Author.Email, []byte("author@example.org")) {
t.Fatalf("author email = %q, want %q", parsed.Author.Email, "author@example.org")
}
if parsed.Author.WhenUnix != 1234567890 {
t.Fatalf("author time = %d, want %d", parsed.Author.WhenUnix, int64(1234567890))
}
if parsed.Author.OffsetMinutes != -450 {
t.Fatalf("author offset = %d, want %d", parsed.Author.OffsetMinutes, int32(-450))
}
if !bytes.Equal(parsed.Committer.Name, []byte("Test Committer")) {
t.Fatalf("committer name = %q, want %q", parsed.Committer.Name, "Test Committer")
}
if !bytes.Equal(parsed.Committer.Email, []byte("committer@example.org")) {
t.Fatalf("committer email = %q, want %q", parsed.Committer.Email, "committer@example.org")
}
if parsed.Committer.WhenUnix != 1234567999 {
t.Fatalf("committer time = %d, want %d", parsed.Committer.WhenUnix, int64(1234567999))
}
if parsed.Committer.OffsetMinutes != 345 {
t.Fatalf("committer offset = %d, want %d", parsed.Committer.OffsetMinutes, int32(345))
}
if !bytes.Equal(parsed.Message, tc.message) {
t.Fatalf("message = %q, want %q", parsed.Message, tc.message)
}
})
}
})
}
}