1package repository
  2
  3import (
  4	"bytes"
  5	"fmt"
  6	"strings"
  7)
  8
  9type TreeEntry struct {
 10	ObjectType ObjectType
 11	Hash       Hash
 12	Name       string
 13}
 14
 15type ObjectType int
 16
 17const (
 18	Unknown ObjectType = iota
 19	Blob
 20	Tree
 21)
 22
 23func ParseTreeEntry(line string) (TreeEntry, error) {
 24	fields := strings.Fields(line)
 25
 26	if len(fields) < 4 {
 27		return TreeEntry{}, fmt.Errorf("Invalid input to parse as a TreeEntry")
 28	}
 29
 30	objType, err := ParseObjectType(fields[0], fields[1])
 31
 32	if err != nil {
 33		return TreeEntry{}, err
 34	}
 35
 36	hash := Hash(fields[2])
 37	name := strings.Join(fields[3:], "")
 38
 39	return TreeEntry{
 40		ObjectType: objType,
 41		Hash:       hash,
 42		Name:       name,
 43	}, nil
 44}
 45
 46// Format the entry as a git ls-tree compatible line
 47func (entry TreeEntry) Format() string {
 48	return fmt.Sprintf("%s %s\t%s\n", entry.ObjectType.Format(), entry.Hash, entry.Name)
 49}
 50
 51func (ot ObjectType) Format() string {
 52	switch ot {
 53	case Blob:
 54		return "100644 blob"
 55	case Tree:
 56		return "040000 tree"
 57	default:
 58		panic("Unknown git object type")
 59	}
 60}
 61
 62func ParseObjectType(mode, objType string) (ObjectType, error) {
 63	switch {
 64	case mode == "100644" && objType == "blob":
 65		return Blob, nil
 66	case mode == "040000" && objType == "tree":
 67		return Tree, nil
 68	default:
 69		return Unknown, fmt.Errorf("Unknown git object type %s %s", mode, objType)
 70	}
 71}
 72
 73func prepareTreeEntries(entries []TreeEntry) bytes.Buffer {
 74	var buffer bytes.Buffer
 75
 76	for _, entry := range entries {
 77		buffer.WriteString(entry.Format())
 78	}
 79
 80	return buffer
 81}
 82
 83func readTreeEntries(s string) ([]TreeEntry, error) {
 84	split := strings.Split(strings.TrimSpace(s), "\n")
 85
 86	casted := make([]TreeEntry, len(split))
 87	for i, line := range split {
 88		if line == "" {
 89			continue
 90		}
 91
 92		entry, err := ParseTreeEntry(line)
 93
 94		if err != nil {
 95			return nil, err
 96		}
 97
 98		casted[i] = entry
 99	}
100
101	return casted, nil
102}