diff --git a/spike/review/reinvent/ezmded/server/tree.go b/spike/review/reinvent/ezmded/server/tree.go new file mode 100644 index 0000000..2b93d9b --- /dev/null +++ b/spike/review/reinvent/ezmded/server/tree.go @@ -0,0 +1,79 @@ +package main + +import ( + "errors" + "io/ioutil" + "os" + "time" + + yaml "gopkg.in/yaml.v2" +) + +type Tree struct { + path string +} + +type Branch struct { + Title string + Deleted bool + Updated time.Time + PID string +} + +func NewTree(path string) *Tree { + return &Tree{ + path: path, + } +} + +func (tree *Tree) Get() (map[string]Branch, error) { + b, err := ioutil.ReadFile(tree.path) + if os.IsNotExist(err) { + return map[string]Branch{}, nil + } + if err != nil { + return nil, err + } + var m map[string]Branch + err = yaml.Unmarshal(b, &m) + return m, err +} + +func (tree *Tree) Set(m map[string]Branch) error { + b, err := yaml.Marshal(m) + if err != nil { + return err + } + return ioutil.WriteFile(tree.path, b, os.ModePerm) +} + +func (tree *Tree) Del(id string) error { + m, err := tree.Get() + if err != nil { + return err + } + branch, ok := m[id] + if !ok { + return nil + } + branch.Updated = time.Now().UTC() + branch.Deleted = true + m[id] = branch + return tree.Set(m) +} + +func (tree *Tree) Put(id string, branch Branch) error { + branch.Updated = time.Now().UTC() + if branch.Title == "" { + branch.Title = "Untitled (" + time.Now().UTC().String() + ")" + } + m, err := tree.Get() + if err != nil { + return err + } + if _, ok := m[branch.PID]; !ok && branch.PID != "" { + return errors.New("PID does not exist") + } + m[id] = branch + return tree.Set(m) +} diff --git a/spike/review/reinvent/ezmded/server/tree_test.go b/spike/review/reinvent/ezmded/server/tree_test.go new file mode 100644 index 0000000..d509b42 --- /dev/null +++ b/spike/review/reinvent/ezmded/server/tree_test.go @@ -0,0 +1,54 @@ +package main + +import ( + "path" + "testing" + "time" +) + +func TestTree(t *testing.T) { + path := path.Join(t.TempDir(), "index.yaml") + tree := NewTree(path) + + if m, err := tree.Get(); err != nil { + t.Fatal(err) + } else if m == nil { + t.Fatal(m) + } + + if err := tree.Del("id"); err != nil { + t.Fatal(err) + } + + if err := tree.Put("id", Branch{PID: "fake"}); err == nil { + t.Fatal(err) + } + + if err := tree.Put("id", Branch{}); err != nil { + t.Fatal(err) + } else if branches, err := tree.Get(); err != nil { + t.Fatal(err) + } else if branch, ok := branches["id"]; !ok { + t.Fatal(err) + } else if branch.Title == "" { + t.Fatal(branch) + } else if time.Since(branch.Updated) > time.Hour { + t.Fatal(branch) + } else if branch.Deleted { + t.Fatal(branch) + } + + if err := tree.Put("id2", Branch{PID: "id"}); err != nil { + t.Fatal(err) + } + + if err := tree.Del("id"); err != nil { + t.Fatal(err) + } else if branches, err := tree.Get(); err != nil { + t.Fatal(err) + } else if branch, ok := branches["id"]; !ok { + t.Fatal(ok) + } else if !branch.Deleted { + t.Fatal(branch) + } +}