1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
package objects
import (
"bytes"
"errors"
"fmt"
"io"
"strings"
"time"
)
type Snapshot struct {
Tree ObjectId
Date time.Time
Container string
Comment string
}
func (s Snapshot) Type() ObjectType {
return OTSnapshot
}
func appendKVPair(b []byte, k, v string) []byte {
b = append(b, []byte(k)...)
b = append(b, ' ')
b = append(b, []byte(v)...)
b = append(b, '\n')
return b
}
func (s Snapshot) Payload() (out []byte) {
out = appendKVPair(out, "container", s.Container)
out = appendKVPair(out, "date", s.Date.Format(time.RFC3339))
out = appendKVPair(out, "tree", s.Tree.String())
if s.Comment != "" {
out = append(out, '\n')
out = append(out, []byte(s.Comment)...)
}
return out
}
func (s *Snapshot) FromPayload(payload []byte) error {
r := bytes.NewBuffer(payload)
seenContainer := false
seenDate := false
seenTree := false
for {
line, err := r.ReadString('\n')
if err != nil && err != io.EOF {
return err
}
line = strings.TrimSpace(line)
if line == "" {
break // Header read successfully
}
parts := strings.SplitN(line, " ", 2)
if len(parts) != 2 {
return fmt.Errorf("Invalid header: %s", line)
}
headerval := strings.TrimSpace(parts[1])
switch parts[0] {
case "container":
s.Container = headerval
seenContainer = true
case "date":
d, err := time.Parse(time.RFC3339, headerval)
if err != nil {
return err
}
s.Date = d
seenDate = true
case "tree":
oid, err := ParseObjectId(headerval)
if err != nil {
return err
}
s.Tree = oid
seenTree = true
}
if err == io.EOF {
break
}
}
if !seenContainer || !seenDate || !seenTree {
return errors.New("Missing container, date or tree header")
}
b := new(bytes.Buffer)
if _, err := io.Copy(b, r); err != nil {
return err
}
s.Comment = strings.TrimSpace(string(b.Bytes()))
return nil
}
func (a Snapshot) Equals(b Snapshot) bool {
return a.Tree.Equals(b.Tree) &&
a.Container == b.Container &&
a.Date.Equal(b.Date) &&
a.Comment == b.Comment
}
|