mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-12-13 22:00:27 +00:00
121 lines
3.2 KiB
Plaintext
121 lines
3.2 KiB
Plaintext
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"log"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
|
|
"github.com/bouncepaw/mycorrhiza/cfg"
|
|
)
|
|
|
|
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.
|
|
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
|
|
}
|
|
return simpleMatch(name, metaJsonPattern),
|
|
simpleMatch(name, hyphaPattern)
|
|
}
|
|
|
|
// scanHyphaDir scans directory at `fullPath` and tells what it has found.
|
|
func scanHyphaDir(fullPath string) (valid bool, possibleSubhyphae []string, metaJsonPath string, err error) {
|
|
nodes, err := ioutil.ReadDir(fullPath)
|
|
if err != nil {
|
|
return // implicit return values
|
|
}
|
|
|
|
for _, node := range nodes {
|
|
metaJsonM, hyphaM := matchNameToEverything(node.Name())
|
|
switch {
|
|
case hyphaM && node.IsDir():
|
|
possibleSubhyphae = append(possibleSubhyphae, filepath.Join(fullPath, node.Name()))
|
|
case metaJsonM && !node.IsDir():
|
|
metaJsonPath = filepath.Join(fullPath, "meta.json")
|
|
// Other nodes are ignored. It is not promised they will be ignored in future versions
|
|
}
|
|
}
|
|
|
|
if metaJsonPath != "" {
|
|
valid = true
|
|
}
|
|
return // implicit return values
|
|
}
|
|
|
|
// hyphaName gets name of a hypha by stripping path to the hypha in `fullPath`
|
|
func hyphaName(fullPath string) string {
|
|
// {cfg.WikiDir}/{the name}
|
|
return fullPath[len(cfg.WikiDir)+1:]
|
|
}
|
|
|
|
// recurFindHyphae recursively searches for hyphae in passed directory path.
|
|
func recurFindHyphae(fullPath string) map[string]*Hypha {
|
|
hyphae := make(map[string]*Hypha)
|
|
valid, possibleSubhyphae, metaJsonPath, err := scanHyphaDir(fullPath)
|
|
if err != nil {
|
|
return hyphae
|
|
}
|
|
|
|
// First, let's process subhyphae
|
|
for _, possibleSubhypha := range possibleSubhyphae {
|
|
for k, v := range recurFindHyphae(possibleSubhypha) {
|
|
hyphae[k] = v
|
|
}
|
|
}
|
|
|
|
// This folder is not a hypha itself, nothing to do here
|
|
if !valid {
|
|
return hyphae
|
|
}
|
|
|
|
// Template hypha struct. Other fields are default json values.
|
|
h := Hypha{
|
|
FullName: hyphaName(fullPath),
|
|
Path: fullPath,
|
|
parentName: filepath.Dir(hyphaName(fullPath)),
|
|
// Children names are unknown now
|
|
}
|
|
|
|
metaJsonContents, err := ioutil.ReadFile(metaJsonPath)
|
|
if err != nil {
|
|
log.Printf("Error when reading `%s`; skipping", metaJsonPath)
|
|
return hyphae
|
|
}
|
|
err = json.Unmarshal(metaJsonContents, &h)
|
|
if err != nil {
|
|
log.Printf("Error when unmarshaling `%s`; skipping", metaJsonPath)
|
|
log.Println(err)
|
|
return hyphae
|
|
}
|
|
|
|
// 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)
|
|
}
|
|
rev.TextPath = filepath.Join(fullPath, rev.TextName)
|
|
}
|
|
|
|
// Now the hypha should be ok, gotta send structs
|
|
hyphae[h.FullName] = &h
|
|
return hyphae
|
|
}
|