summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2024-05-11 18:53:16 +0300
committerPaul Buetow <paul@buetow.org>2024-05-11 18:53:16 +0300
commitb97854c8ec2665887121d773ab994a09ca768adb (patch)
treef673318257f0a172f8cf7784feea2633ccd1ac4a
parent560b685505a43aa1a1365c1c3f7b3d0733676847 (diff)
also return the checksums for each element of the repository
-rw-r--r--cmd/gosd/main.go4
-rw-r--r--internal/server/handle/handle.go18
-rw-r--r--internal/server/repository/repository.go56
-rw-r--r--internal/types/entry.go71
-rw-r--r--internal/types/entry_test.go22
5 files changed, 143 insertions, 28 deletions
diff --git a/cmd/gosd/main.go b/cmd/gosd/main.go
index eb018c3..06a0353 100644
--- a/cmd/gosd/main.go
+++ b/cmd/gosd/main.go
@@ -38,6 +38,10 @@ func main() {
return handle.Get(w, r, conf.DataDir)
})
+ serv.Handle("merge", func(w http.ResponseWriter, r *http.Request) error {
+ return handle.Merge(w, r, conf.DataDir)
+ })
+
log.Println("Server is starting on", conf.ListenAddr)
if err := http.ListenAndServe(conf.ListenAddr, nil); err != err {
log.Fatal("error starting server:", err)
diff --git a/internal/server/handle/handle.go b/internal/server/handle/handle.go
index d1f7748..55f7b3e 100644
--- a/internal/server/handle/handle.go
+++ b/internal/server/handle/handle.go
@@ -1,7 +1,6 @@
package handle
import (
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -49,19 +48,13 @@ func List(w http.ResponseWriter, r *http.Request, dataDir string) error {
return fmt.Errorf("expexted GET request")
}
- repository := repository.New(dataDir)
- ids, err := repository.List()
+ list, err := repository.New(dataDir).List()
if err != nil {
return err
}
- jsonData, err := json.Marshal(ids)
- if err != nil {
- return err
- }
-
- fmt.Fprint(w, string(jsonData))
- return nil
+ _, err = w.Write(list)
+ return err
}
func Get(w http.ResponseWriter, r *http.Request, dataDir string) error {
@@ -78,3 +71,8 @@ func Get(w http.ResponseWriter, r *http.Request, dataDir string) error {
fmt.Fprint(w, string(data))
return nil
}
+
+func Merge(w http.ResponseWriter, r *http.Request, dataDir string) error {
+
+ return nil
+}
diff --git a/internal/server/repository/repository.go b/internal/server/repository/repository.go
index 5fe79fd..7eb7122 100644
--- a/internal/server/repository/repository.go
+++ b/internal/server/repository/repository.go
@@ -1,36 +1,76 @@
package repository
import (
+ "encoding/json"
"log"
"os"
"path/filepath"
"strings"
+ "sync"
+
+ "codeberg.org/snonux/gos/internal/types"
)
type Repository struct {
dataDir string
+ entries map[string]types.Entry
+ mu *sync.Mutex
}
func New(dataDir string) Repository {
- return Repository{dataDir}
+ return Repository{
+ dataDir: dataDir,
+ entries: make(map[string]types.Entry),
+ mu: &sync.Mutex{},
+ }
}
-func (r Repository) List() ([]string, error) {
- var ids []string
+func (r Repository) store(entry types.Entry) {
+ r.mu.Lock()
+ defer r.mu.Unlock()
+ r.entries[entry.ID] = entry
+}
- visit := func(files *[]string) filepath.WalkFunc {
+// Load repository into memory
+func (r Repository) load() error {
+ visit := func() filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
log.Println(err)
return nil
}
- if !info.IsDir() && strings.HasSuffix(path, ".json") {
- *files = append(*files, strings.TrimPrefix(path, r.dataDir))
+ if info.IsDir() || !strings.HasSuffix(path, ".json") {
+ return nil
+ }
+
+ entry, err := types.NewEntryFromFile(path)
+ if err != err {
+ return err
}
+ r.store(entry)
return nil
}
}
- err := filepath.Walk(r.dataDir, visit(&ids))
- return ids, err
+ return filepath.Walk(r.dataDir, visit())
+}
+
+func (r Repository) List() ([]byte, error) {
+ if err := r.load(); err != nil {
+ return []byte{}, err
+ }
+
+ type pair struct {
+ ID, Checksum string
+ }
+
+ var pairs []pair
+ r.mu.Lock()
+ defer r.mu.Unlock()
+
+ for _, entry := range r.entries {
+ pairs = append(pairs, pair{entry.ID, entry.Checksum()})
+ }
+
+ return json.Marshal(pairs)
}
diff --git a/internal/types/entry.go b/internal/types/entry.go
index a274e2c..067d849 100644
--- a/internal/types/entry.go
+++ b/internal/types/entry.go
@@ -4,31 +4,82 @@ import (
"crypto/sha256"
"encoding/json"
"fmt"
+ "os"
+ "strings"
+ "sync"
)
+// Tells me whether the entry was shared to the sm platform named Name
type Shared struct {
Name string `json:"id"`
Is bool `json:"is,omitempty"`
}
+func (s Shared) String() string {
+ return fmt.Sprintf("Name:%s\nIs:%v\n", s.Name, s.Is)
+}
+
type Entry struct {
- Body string `json:"body"`
- Shared []Shared `json:"shared,omitempty"`
- Epoch int `json:"epoch,omitempty"`
- ID string `json:"id,omitempty"`
+ Body string `json:"body"`
+ Shared []Shared `json:"shared,omitempty"`
+ Epoch int `json:"epoch,omitempty"`
+ ID string `json:"id,omitempty"`
+ mu *sync.Mutex
+ dirty bool
+ checksum string
}
func NewEntry(bytes []byte) (Entry, error) {
- var entry Entry
- if err := json.Unmarshal(bytes, &entry); err != nil {
- return entry, fmt.Errorf("unable to deserialise payload: %w", err)
+ var ent Entry
+ if err := json.Unmarshal(bytes, &ent); err != nil {
+ return ent, fmt.Errorf("unable to deserialise payload: %w", err)
}
- if entry.ID == "" {
- entry.ID = fmt.Sprintf("%x", sha256.Sum256(bytes))
+ ent.mu = &sync.Mutex{}
+ ent.dirty = true
+ if ent.ID == "" {
+ ent.ID = fmt.Sprintf("%x", sha256.Sum256(bytes))
+ }
+ return ent, nil
+}
+
+func NewEntryFromFile(filePath string) (Entry, error) {
+ bytes, err := os.ReadFile(filePath)
+ if err != err {
+ return Entry{}, err
}
- return entry, nil
+ return NewEntry(bytes)
}
func (e Entry) Serialize() ([]byte, error) {
return json.Marshal(e)
}
+
+func (e Entry) String() string {
+ var sb strings.Builder
+
+ sb.WriteString("ID:")
+ sb.WriteString(e.ID)
+ sb.WriteString("\n")
+ sb.WriteString(fmt.Sprintf("Epoch:%d\n", e.Epoch))
+ for _, shared := range e.Shared {
+ sb.WriteString(shared.String())
+ }
+ sb.WriteString("Body:")
+ sb.WriteString(e.Body)
+ sb.WriteString("\n")
+
+ return sb.String()
+}
+
+func (e *Entry) Checksum() string {
+ e.mu.Lock()
+ defer e.mu.Unlock()
+
+ if !e.dirty {
+ return e.checksum
+ }
+
+ e.checksum = fmt.Sprintf("%x", sha256.Sum256([]byte(e.String())))
+ e.dirty = false
+ return e.checksum
+}
diff --git a/internal/types/entry_test.go b/internal/types/entry_test.go
new file mode 100644
index 0000000..65e74a3
--- /dev/null
+++ b/internal/types/entry_test.go
@@ -0,0 +1,22 @@
+package types
+
+import "testing"
+
+func TestEntryChecksum(t *testing.T) {
+ t.Parallel()
+
+ ent, err := NewEntry([]byte(`{"Body": "Body text here"}`))
+ if err != nil {
+ t.Error(err)
+ return
+ }
+
+ expected := "8618a63380fe6d365422cae6ef143a88bb6bd78df567fea3822074cc748f52f8"
+ got := ent.Checksum()
+
+ if expected != got {
+ t.Errorf("expected checksum '%s' but got '%s'", expected, got)
+ return
+ }
+ t.Log(ent.Checksum())
+}