Initial commit

Olivier Tremblay 3 years ago
commit
b9c4bccf7e
1 changed files with 153 additions and 0 deletions
  1. 153 0
      main.go

+ 153 - 0
main.go

@@ -0,0 +1,153 @@
1
+package main
2
+
3
+import (
4
+	"bytes"
5
+	"encoding/gob"
6
+	"errors"
7
+	"fmt"
8
+	"io"
9
+	"net/http"
10
+	"os"
11
+	"strconv"
12
+
13
+	"github.com/boltdb/bolt"
14
+	"github.com/kr/binarydist"
15
+)
16
+
17
+var ErrDiffNotFound = errors.New("Diff not found for key provided")
18
+
19
+func main() {
20
+	bd, err := bolt.Open(os.Args[1], 0666, nil)
21
+	if err != nil {
22
+		panic(err)
23
+	}
24
+	r := http.NewServeMux()
25
+	r.HandleFunc("/", func(rw http.ResponseWriter, req *http.Request) {
26
+		rw.Header().Add("Access-Control-Allow-Origin", "*")
27
+		rw.Header().Add("Access-Control-Expose-Headers", "X-DocVersion")
28
+		rw.Header().Add("Access-Control-Allow-Headers", "X-DocVersion")
29
+		obj := req.URL.Path
30
+		if obj != "" {
31
+			version := -1
32
+			if v := req.Header.Get("X-Docversion"); v != "" {
33
+				if i, err := strconv.Atoi(v); err == nil {
34
+					version = i
35
+					fmt.Println(version)
36
+				}
37
+
38
+			}
39
+
40
+			if req.Method == "GET" {
41
+				bd.View(func(t *bolt.Tx) error {
42
+					b := t.Bucket([]byte("diffs"))
43
+					if b == nil {
44
+						return ErrDiffNotFound
45
+					}
46
+					val := b.Get([]byte(obj))
47
+					if val == nil {
48
+						return ErrDiffNotFound
49
+					}
50
+					var diff_bytes = bytes.NewBuffer(val)
51
+					dec := gob.NewDecoder(diff_bytes)
52
+					var d *diff
53
+					err = dec.Decode(&d)
54
+					if err != nil {
55
+						return err
56
+					}
57
+					out, v, err := d.Apply(version)
58
+					if err != nil {
59
+						fmt.Println(err)
60
+						return err
61
+					}
62
+					rw.Header().Add("X-Docversion", strconv.Itoa(v))
63
+
64
+					fmt.Fprintf(rw, string(out))
65
+					return err
66
+				})
67
+			}
68
+			if req.Method == "POST" {
69
+				bd.Update(func(t *bolt.Tx) error {
70
+					obj_address := []byte(obj)
71
+					b, err := t.CreateBucketIfNotExists([]byte("diffs"))
72
+					if err != nil {
73
+						return err
74
+					}
75
+					existing := b.Get(obj_address)
76
+					if existing == nil {
77
+						original := &diff{}
78
+						var out bytes.Buffer
79
+						io.Copy(&out, req.Body)
80
+
81
+						original.Patch = out.Bytes()
82
+						var bb bytes.Buffer
83
+						enc := gob.NewEncoder(&bb)
84
+						enc.Encode(original)
85
+						return b.Put(obj_address, bb.Bytes())
86
+					}
87
+
88
+					diff_bytes := bytes.NewBuffer(existing)
89
+					diff_dec := gob.NewDecoder(diff_bytes)
90
+					var d *diff
91
+					diff_dec.Decode(&d)
92
+					applied_diff, _, err := d.Apply(-1)
93
+					if err != nil {
94
+						return err
95
+					}
96
+					var new_patch bytes.Buffer
97
+					err = binarydist.Diff(bytes.NewBuffer(applied_diff), req.Body, &new_patch)
98
+					if err != nil {
99
+						return err
100
+					}
101
+					d.Append(&diff{Patch: new_patch.Bytes()})
102
+					var out bytes.Buffer
103
+					enc := gob.NewEncoder(&out)
104
+					enc.Encode(d)
105
+					err = b.Put(obj_address, out.Bytes())
106
+					return err
107
+				})
108
+			}
109
+		}
110
+	})
111
+
112
+	err = http.ListenAndServe(":8081", r)
113
+	if err != nil {
114
+		panic(err)
115
+	}
116
+}
117
+
118
+type diff struct {
119
+	Patch    []byte
120
+	Nextdiff *diff
121
+}
122
+
123
+func (d *diff) String() string {
124
+	s2 := ""
125
+	if d.Nextdiff != nil {
126
+		s2 = d.Nextdiff.String()
127
+	}
128
+	return fmt.Sprintf("%s %s", string(d.Patch), s2)
129
+}
130
+
131
+func (d *diff) Apply(version int) ([]byte, int, error) {
132
+	b := bytes.NewBuffer(d.Patch)
133
+	i := 0
134
+	for nd := d.Nextdiff; nd != nil && (version == -1 || i < version); nd = nd.Nextdiff {
135
+		bp := bytes.NewBuffer(nd.Patch)
136
+		var bn bytes.Buffer
137
+		err := binarydist.Patch(b, &bn, bp)
138
+		if err != nil {
139
+			return nil, -1, err
140
+		}
141
+		b = &bn
142
+		i++
143
+	}
144
+	return b.Bytes(), i, nil
145
+}
146
+
147
+func (d *diff) Append(d2 *diff) {
148
+	od := d
149
+	for nd := od.Nextdiff; nd != nil; nd = nd.Nextdiff {
150
+		od = nd
151
+	}
152
+	od.Nextdiff = d2
153
+}