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}