dati

A Go library/binary to parse & execute data against template langauges.
git clone git://src.gearsix.net/dati
Log | Files | Refs | Atom | README | LICENSE

commit 49f66e430c521eb9a2af3b32ffd3aa4c10724520
parent 24618687363e96a18523ac2d3e2815e862d14e93
Author: gearsix <gearsix@tuta.io>
Date:   Wed,  3 Mar 2021 21:14:49 +0000

added sortFileData & tests for checking it; ran gofmt

Diffstat:
Msrc/data.go | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Msrc/data_test.go | 91+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/suti.go | 29++++++++++++++++-------------
Msrc/template.go | 8++++----
Msrc/template_test.go | 9++++-----
5 files changed, 149 insertions(+), 51 deletions(-)

diff --git a/src/data.go b/src/data.go @@ -6,8 +6,10 @@ import ( "io" "io/ioutil" "os" + "time" "path/filepath" "strings" + "sort" ) type Data map[string]interface{} @@ -48,7 +50,7 @@ func LoadDataFile(path string) (Data, error) { } // LoadDataFiles TODO -func LoadDataFiles(paths ...string) map[string]Data { +func LoadDataFiles(order string, paths ...string) []Data { var err error var stat os.FileInfo var d Data @@ -58,7 +60,7 @@ func LoadDataFiles(paths ...string) map[string]Data { for p, path := range paths { if strings.Contains(path, "*") { if glob, e := filepath.Glob(path); e == nil { - paths = append(paths, glob...) + paths = append(paths, glob...) paths = append(paths[:p], paths[p+1:]...) } else { warn("error parsing glob '%s': %s", path, err) @@ -83,13 +85,65 @@ func LoadDataFiles(paths ...string) map[string]Data { } return e }) - } else if d, err = LoadDataFile(path); err == nil { + } else if d, err = LoadDataFile(path); err == nil { loaded[path] = d } else { warn("skipping data file '%s' (%s)", path, err) } } } + + return sortFileData(loaded, order) +} - return loaded +func sortFileData(data map[string]Data, order string) []Data { + sorted := make([]Data, 0, len(data)) + + if order == "filename" { + fnames := make([]string, 0, len(data)) + for fpath, _ := range data { + fnames = append(fnames, filepath.Base(fpath)) + } + sort.Strings(fnames) + for _, fname := range fnames { + for fpath, d := range data { + if fname == filepath.Base(fpath) { + sorted = append(sorted, d) + } + } + } + } else if order == "modified" { + stats := make(map[string]os.FileInfo) + for fpath, _ := range data { + if stat, err := os.Stat(fpath); err != nil { + warn("failed to stat %s (%s)", fpath, err) + } else { + stats[fpath] = stat + } + } + + modtimes := make([]time.Time, 0, len(data)) + for _, stat := range stats { + modtimes = append(modtimes, stat.ModTime()) + } + sort.Slice(modtimes, func(i, j int) bool { + return modtimes[i].Before(modtimes[j]) + }) + + for _, t := range modtimes { + for fpath, stat := range stats { + if t == stat.ModTime() { + sorted = append(sorted, data[fpath]) + } + } + } + } else { + warn("unrecognised sort option '%s', data will be unsorted", order) + for _, d := range data { + sorted = append(sorted, d) + } + } + + return sorted } + +\ No newline at end of file diff --git a/src/data_test.go b/src/data_test.go @@ -1,17 +1,19 @@ package main import ( + "encoding/json" + "os" "strings" "testing" - "os" ) -const goodJson = `{"example": 1}` +const goodJson1 = `{"example1":0}` +const goodJson2 = `{"example2":1}` const badJson = `{"example":2:]}}` func writeTestFile(path string, Data string) (e error) { var f *os.File - + if f, e = os.Create(path); e != nil { return } @@ -19,65 +21,105 @@ func writeTestFile(path string, Data string) (e error) { return } f.Close() - + return } func TestLoadData(t *testing.T) { var d Data var e error - - if d, e = LoadData("json", strings.NewReader(goodJson)); e != nil { + + if d, e = LoadData("json", strings.NewReader(goodJson1)); e != nil { t.Error(e) + } else if len(d) == 0 { + t.Error("no data loaded") } - if len(d) == 0 { - t.Fail() - } else { - t.Log(d) - } - + if d, e = LoadData("json", strings.NewReader(badJson)); e == nil { t.Error("bad.json passed") } + if d, e = LoadData("json", strings.NewReader("")); e == nil { + t.Error("empty file passed") + } + return } func TestLoadDataFiles(t *testing.T) { var e error var p []string - var d map[string]Data + var b []byte + var d []Data tdir := t.TempDir() - - p = append(p, tdir+"/good.json") - if e = writeTestFile(p[0], goodJson); e != nil { + + p = append(p, tdir+"/good2.json") + if e = writeTestFile(p[0], goodJson2); e != nil { t.Skip("setup failure:", e) } - p = append(p, tdir+"/good.json") - if e = writeTestFile(p[1], goodJson); e != nil { + p = append(p, tdir+"/good1.json") + if e = writeTestFile(p[1], goodJson1); e != nil { + t.Skip("setup failure:", e) + } + p = append(p, tdir+"/good1.json") + if e = writeTestFile(p[2], goodJson1); e != nil { t.Skip("setup failure:", e) } p = append(p, tdir+"/bad.json") - if e = writeTestFile(p[2], badJson); e != nil { + if e = writeTestFile(p[3], badJson); e != nil { t.Skip("setup failure:", e) } - - d = LoadDataFiles(tdir) + + d = LoadDataFiles("filename", tdir) if len(d) == len(p) { t.Error("bad.json passed") } else if len(d) == 0 { t.Error("no data loaded") + } else { + if b, e = json.Marshal(d[0]); e != nil { + t.Error(e) + } else if string(b) == goodJson2 { + t.Error("data returned out of order") + } else if string(b) != goodJson1 { + t.Errorf("incorrect json: %s does not match %s", b, goodJson1) + } + + if b, e = json.Marshal(d[1]); e != nil { + t.Error(e) + } else if string(b) == goodJson1 { + t.Error("data returned out of order") + } else if string(b) != goodJson2 { + t.Errorf("incorrect json: %s does not match %s", b, goodJson2) + } } - d = LoadDataFiles(p...) + + d = LoadDataFiles("modified", p...) if len(d) == len(p) { t.Error("bad.json passed") } else if len(d) == 0 { t.Error("no data loaded") + } else { + if b, e = json.Marshal(d[0]); e != nil { + t.Error(e) + } else if string(b) == goodJson1 { + t.Error("data returned out of order") + } else if string(b) != goodJson2 { + t.Errorf("incorrect json: %s does not match %s", b, goodJson1) + } + + if b, e = json.Marshal(d[1]); e != nil { + t.Error(e) + } else if string(b) == goodJson2 { + t.Error("data returned out of order") + } else if string(b) != goodJson1 { + t.Errorf("incorrect json: %s does not match %s", b, goodJson2) + } } - d = LoadDataFiles(tdir+"/*") + + d = LoadDataFiles("", tdir + "/*") if len(d) == len(p) { t.Error("bad.json passed") } else if len(d) == 0 { t.Error("no data loaded") } -} -\ No newline at end of file +} diff --git a/src/suti.go b/src/suti.go @@ -6,13 +6,13 @@ import ( ) type Options struct { - RootPaths []string - PartialPaths []string - GlobalDataPaths []string - DataPaths []string - DataKey string - SortData string - ConfigFile string + RootPaths []string + PartialPaths []string + GlobalDataPaths []string + DataPaths []string + DataKey string + SortData string + ConfigFile string } var options Options @@ -22,7 +22,7 @@ func init() { print("nothing to do") os.Exit(0) } - + options = parseArgs(os.Args[1:]) if len(options.SortData) == 0 { options.SortData = "filename" @@ -30,15 +30,18 @@ func init() { } func main() { - - _ = LoadDataFiles(options.GlobalDataPaths...) - _ = LoadDataFiles(options.DataPaths...) - + + _ = LoadDataFiles("", options.GlobalDataPaths...) + d := LoadDataFiles(options.SortData, options.DataPaths...) + for k, v := range d { + fmt.Println(k, v) + } + templates := make([]Template, 0) for _, r := range options.RootPaths { if t, e := LoadTemplateFile(r, options.PartialPaths...); e != nil { warn("unable to load templates (%s)", e) - } else { + } else { templates = append(templates, t) } } diff --git a/src/template.go b/src/template.go @@ -2,11 +2,11 @@ package main import ( "fmt" + hmpl "html/template" "os" "path/filepath" "strings" tmpl "text/template" - hmpl "html/template" ) type Template interface{} @@ -27,9 +27,9 @@ func LoadTemplateFile(root string, partials ...string) (t Template, e error) { if e != nil { return } - + ttype := getTemplateType(root) - + if ttype == "tmpl" || ttype == "gotmpl" { var gotmpl *tmpl.Template if gotmpl, e = tmpl.ParseFiles(root); e != nil { @@ -57,6 +57,6 @@ func LoadTemplateFile(root string, partials ...string) (t Template, e error) { } else { e = fmt.Errorf("'%s' is not a supported template language", ttype) } - + return } diff --git a/src/template_test.go b/src/template_test.go @@ -18,7 +18,7 @@ func TestLoadTemplateFile(t *testing.T) { var e error var gr, gp, br, bp []string tdir := t.TempDir() - + gr = append(gr, tdir+"/goodRoot.tmpl") if e = writeTestFile(gr[0], tmplRootGood); e != nil { t.Skip("setup failure:", e) @@ -35,7 +35,7 @@ func TestLoadTemplateFile(t *testing.T) { if e = writeTestFile(bp[0], tmplPartialBad); e != nil { t.Skip("setup failure:", e) } - + gr = append(gr, tdir+"/goodRoot.hmpl") if e = writeTestFile(gr[1], hmplRootGood); e != nil { t.Skip("setup failure:", e) @@ -52,7 +52,7 @@ func TestLoadTemplateFile(t *testing.T) { if e = writeTestFile(bp[1], hmplPartialBad); e != nil { t.Skip("setup failure:", e) } - + for _, root := range gr { // good root, good partials if _, e := LoadTemplateFile(root, gp...); e != nil { t.Error(e) @@ -74,4 +74,4 @@ func TestLoadTemplateFile(t *testing.T) { t.Errorf("bad template with bad partials passed\n") } } -} -\ No newline at end of file +}