add TreeEntry to manage the talking with git mktree and git ls-tree

Michael Muré created

Change summary

repository/tree_entry.go      | 72 +++++++++++++++++++++++++++++++++++++
repository/tree_entry_test.go | 34 +++++++++++++++++
2 files changed, 106 insertions(+)

Detailed changes

repository/tree_entry.go 🔗

@@ -0,0 +1,72 @@
+package repository
+
+import (
+	"fmt"
+	"github.com/MichaelMure/git-bug/util"
+	"github.com/pkg/errors"
+	"strings"
+)
+
+type TreeEntry struct {
+	ObjectType ObjectType
+	Hash       util.Hash
+	Name       string
+}
+
+type ObjectType int
+
+const (
+	Unknown ObjectType = iota
+	Blob
+	Tree
+)
+
+func ParseTreeEntry(line string) (TreeEntry, error) {
+	fields := strings.Fields(line)
+
+	if len(fields) < 4 {
+		return TreeEntry{}, errors.New("Invalid input to parse as a TreeEntry")
+	}
+
+	objType, err := ParseObjectType(fields[0], fields[1])
+
+	if err != nil {
+		return TreeEntry{}, err
+	}
+
+	hash := util.Hash(fields[2])
+	name := strings.Join(fields[3:], "")
+
+	return TreeEntry{
+		ObjectType: objType,
+		Hash:       hash,
+		Name:       name,
+	}, nil
+}
+
+// Format the entry as a git ls-tree compatible line
+func (entry TreeEntry) Format() string {
+	return fmt.Sprintf("%s %s\t%s\n", entry.ObjectType.Format(), entry.Hash, entry.Name)
+}
+
+func (ot ObjectType) Format() string {
+	switch ot {
+	case Blob:
+		return "100644 blob"
+	case Tree:
+		return "040000 tree"
+	default:
+		panic("Unknown git object type")
+	}
+}
+
+func ParseObjectType(mode, objType string) (ObjectType, error) {
+	switch {
+	case mode == "100644" && objType == "blob":
+		return Blob, nil
+	case mode == "040000" && objType == "tree":
+		return Tree, nil
+	default:
+		return Unknown, errors.Errorf("Unknown git object type %s %s", mode, objType)
+	}
+}

repository/tree_entry_test.go 🔗

@@ -0,0 +1,34 @@
+package repository
+
+import (
+	"github.com/MichaelMure/git-bug/util"
+	"testing"
+)
+
+func TestTreeEntryFormat(t *testing.T) {
+
+	entries := []TreeEntry{
+		{Blob, util.Hash("a85730cf5287d40a1e32d3a671ba2296c73387cb"), "name"},
+		{Tree, util.Hash("a85730cf5287d40a1e32d3a671ba2296c73387cb"), "name"},
+	}
+
+	for _, entry := range entries {
+		_ = entry.Format()
+	}
+}
+
+func TestTreeEntryParse(t *testing.T) {
+	lines := []string{
+		"100644 blob 1e5ffaffc67049635ba7b01f77143313503f1ca1	.gitignore",
+		"040000 tree 728421fea4168b874bc1a8aa409d6723ef445a4e	bug",
+	}
+
+	for _, line := range lines {
+		_, err := ParseTreeEntry(line)
+
+		if err != nil {
+			t.Fatal(err)
+		}
+	}
+
+}