aboutsummaryrefslogtreecommitdiff
path: root/objects/object_snapshot.go
diff options
context:
space:
mode:
Diffstat (limited to 'objects/object_snapshot.go')
-rw-r--r--objects/object_snapshot.go111
1 files changed, 111 insertions, 0 deletions
diff --git a/objects/object_snapshot.go b/objects/object_snapshot.go
new file mode 100644
index 0000000..a161f27
--- /dev/null
+++ b/objects/object_snapshot.go
@@ -0,0 +1,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
+}