1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-05 17:40:26 +00:00
mycorrhiza/walk.go

121 lines
3.2 KiB
Go
Raw Normal View History

2020-06-12 16:22:02 +00:00
package main
import (
"encoding/json"
"io/ioutil"
"log"
2020-06-12 16:22:02 +00:00
"path/filepath"
"regexp"
2020-06-20 15:17:13 +00:00
"strconv"
2020-06-23 17:53:05 +00:00
"github.com/bouncepaw/mycorrhiza/cfg"
2020-06-12 16:22:02 +00:00
)
const (
hyphaPattern = `[^\s\d:/?&\\][^:?&\\]*`
hyphaUrl = `/{hypha:` + hyphaPattern + `}`
revisionPattern = `[\d]+`
revQuery = `{rev:` + revisionPattern + `}`
metaJsonPattern = `meta\.json`
)
var (
leadingInt = regexp.MustCompile(`^[-+]?\d+`)
)
// matchNameToEverything matches `name` to all filename patterns and returns 4 boolean results.
2020-06-20 15:17:13 +00:00
func matchNameToEverything(name string) (metaJsonM, hyphaM bool) {
// simpleMatch reduces boilerplate. Errors are ignored because I trust my regex skills.
simpleMatch := func(s string, p string) bool {
m, _ := regexp.MatchString(p, s)
return m
}
2020-06-20 15:17:13 +00:00
return simpleMatch(name, metaJsonPattern),
simpleMatch(name, hyphaPattern)
}
// scanHyphaDir scans directory at `fullPath` and tells what it has found.
2020-06-20 15:17:13 +00:00
func scanHyphaDir(fullPath string) (valid bool, possibleSubhyphae []string, metaJsonPath string, err error) {
2020-06-12 16:22:02 +00:00
nodes, err := ioutil.ReadDir(fullPath)
if err != nil {
return // implicit return values
}
for _, node := range nodes {
2020-06-20 15:17:13 +00:00
metaJsonM, hyphaM := matchNameToEverything(node.Name())
2020-06-12 16:22:02 +00:00
switch {
case hyphaM && node.IsDir():
possibleSubhyphae = append(possibleSubhyphae, filepath.Join(fullPath, node.Name()))
case metaJsonM && !node.IsDir():
metaJsonPath = filepath.Join(fullPath, "meta.json")
2020-06-12 16:22:02 +00:00
// Other nodes are ignored. It is not promised they will be ignored in future versions
}
}
2020-06-20 15:17:13 +00:00
if metaJsonPath != "" {
valid = true
}
2020-06-12 16:22:02 +00:00
return // implicit return values
}
// hyphaName gets name of a hypha by stripping path to the hypha in `fullPath`
2020-06-12 16:22:02 +00:00
func hyphaName(fullPath string) string {
2020-06-23 17:53:05 +00:00
// {cfg.WikiDir}/{the name}
return fullPath[len(cfg.WikiDir)+1:]
2020-06-12 16:22:02 +00:00
}
// recurFindHyphae recursively searches for hyphae in passed directory path.
func recurFindHyphae(fullPath string) map[string]*Hypha {
hyphae := make(map[string]*Hypha)
2020-06-20 15:17:13 +00:00
valid, possibleSubhyphae, metaJsonPath, err := scanHyphaDir(fullPath)
2020-06-12 16:22:02 +00:00
if err != nil {
return hyphae
}
// First, let's process subhyphae
for _, possibleSubhypha := range possibleSubhyphae {
for k, v := range recurFindHyphae(possibleSubhypha) {
hyphae[k] = v
}
2020-06-12 16:22:02 +00:00
}
// This folder is not a hypha itself, nothing to do here
if !valid {
2020-06-12 16:22:02 +00:00
return hyphae
}
// Template hypha struct. Other fields are default json values.
2020-06-12 16:22:02 +00:00
h := Hypha{
FullName: hyphaName(fullPath),
2020-06-12 16:22:02 +00:00
Path: fullPath,
parentName: filepath.Dir(hyphaName(fullPath)),
2020-06-12 16:22:02 +00:00
// Children names are unknown now
}
metaJsonContents, err := ioutil.ReadFile(metaJsonPath)
2020-06-12 16:22:02 +00:00
if err != nil {
log.Printf("Error when reading `%s`; skipping", metaJsonPath)
2020-06-12 16:22:02 +00:00
return hyphae
}
err = json.Unmarshal(metaJsonContents, &h)
2020-06-12 16:22:02 +00:00
if err != nil {
log.Printf("Error when unmarshaling `%s`; skipping", metaJsonPath)
2020-06-20 15:17:13 +00:00
log.Println(err)
2020-06-12 16:22:02 +00:00
return hyphae
}
2020-06-20 15:17:13 +00:00
// fill in rooted paths to content files and full names
for idStr, rev := range h.Revisions {
rev.FullName = filepath.Join(h.parentName, rev.ShortName)
rev.Id, _ = strconv.Atoi(idStr)
if rev.BinaryName != "" {
rev.BinaryPath = filepath.Join(fullPath, rev.BinaryName)
2020-06-12 16:22:02 +00:00
}
2020-06-20 15:17:13 +00:00
rev.TextPath = filepath.Join(fullPath, rev.TextName)
2020-06-12 16:22:02 +00:00
}
// Now the hypha should be ok, gotta send structs
hyphae[h.FullName] = &h
return hyphae
2020-06-12 16:22:02 +00:00
}