1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-12 13:30:26 +00:00
mycorrhiza/walk.go

192 lines
4.8 KiB
Go
Raw Normal View History

2020-06-12 16:22:02 +00:00
package main
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"path/filepath"
"regexp"
"strconv"
)
func scanHyphaDir(fullPath string) (structureMet bool, possibleRevisionPaths []string, possibleHyphaPaths []string, reterr error) {
nodes, err := ioutil.ReadDir(fullPath)
if err != nil {
reterr = err
return // implicit return values
}
var (
mmJsonPresent bool
zeroDirPresent bool
)
for _, node := range nodes {
matchedHypha, _ := regexp.MatchString(hyphaPattern, node.Name())
matchedRev, _ := regexp.MatchString(revisionPattern, node.Name())
switch {
case matchedRev && node.IsDir():
if node.Name() == "0" {
zeroDirPresent = true
}
possibleRevisionPaths = append(
possibleRevisionPaths,
filepath.Join(fullPath, node.Name()),
)
case (node.Name() == "mm.json") && !node.IsDir():
mmJsonPresent = true
case matchedHypha && node.IsDir():
possibleHyphaPaths = append(
possibleHyphaPaths,
filepath.Join(fullPath, node.Name()),
)
// Other nodes are ignored. It is not promised they will be ignored in future versions
}
}
if mmJsonPresent && zeroDirPresent {
structureMet = true
}
return // implicit return values
}
func check(e error) {
if e != nil {
panic(e)
}
}
// Hypha name is rootWikiDir/{here}
func hyphaName(fullPath string) string {
return fullPath[len(rootWikiDir)+1:]
}
const (
hyphaPattern = `[^\s\d:/?&\\][^:?&\\]*`
revisionPattern = `[\d]+`
hyphaUrl = "/{hypha:" + hyphaPattern + "}"
revQuery = `{rev:[\d]+}`
2020-06-12 16:22:02 +00:00
)
// Sends found hyphae to the `ch`. `fullPath` is tested for hyphaness, then its subdirs with hyphaesque names are tested too using goroutines for each subdir. The function is recursive.
func recurFindHyphae(fullPath string) (hyphae []*Hypha) {
structureMet, possibleRevisionPaths, possibleHyphaPaths, err := scanHyphaDir(fullPath)
if err != nil {
return hyphae
}
// First, let's process inner hyphae
for _, possibleHyphaPath := range possibleHyphaPaths {
hyphae = append(hyphae, recurFindHyphae(possibleHyphaPath)...)
}
// This folder is not a hypha itself, nothing to do here
if !structureMet {
return hyphae
}
// Template hypha struct. Other fields are default jsont values.
h := Hypha{
Path: fullPath,
Name: hyphaName(fullPath),
ParentName: filepath.Dir(hyphaName(fullPath)),
// Children names are unknown now
}
// Fill in every revision
for _, possibleRevisionPath := range possibleRevisionPaths {
2020-06-13 11:18:11 +00:00
rev, err := makeRevision(possibleRevisionPath, h.Name)
2020-06-12 16:22:02 +00:00
if err == nil {
h.Revisions = append(h.Revisions, rev)
}
}
mmJsonPath := filepath.Join(fullPath, "mm.json")
mmJsonContents, err := ioutil.ReadFile(mmJsonPath)
if err != nil {
fmt.Println(fullPath, ">\tError:", err)
return hyphae
}
err = json.Unmarshal(mmJsonContents, &h)
if err != nil {
fmt.Println(fullPath, ">\tError:", err)
return hyphae
}
// Now the hypha should be ok, gotta send structs
hyphae = append(hyphae, &h)
return hyphae
}
2020-06-13 11:18:11 +00:00
func makeRevision(fullPath string, fullName string) (r Revision, err error) {
2020-06-12 16:22:02 +00:00
// fullPath is expected to be a path to a dir.
// Revision directory must have at least `m.json` and `t.txt` files.
var (
mJsonPresent bool
tTxtPresent bool
bPresent bool
)
nodes, err := ioutil.ReadDir(fullPath)
if err != nil {
return r, err
}
for _, node := range nodes {
if node.IsDir() {
continue
}
switch node.Name() {
case "m.json":
mJsonPresent = true
case "t.txt":
tTxtPresent = true
case "b":
bPresent = true
}
}
if !(mJsonPresent && tTxtPresent) {
return r, errors.New("makeRevision: m.json and t.txt files are not found")
}
// If all the flags are true, this directory is assumed to be a revision. Gotta check further. This is template Revision struct. Other fields fall back to default init values.
mJsonPath := filepath.Join(fullPath, "m.json")
mJsonContents, err := ioutil.ReadFile(mJsonPath)
if err != nil {
fmt.Println(fullPath, ">\tError:", err)
return r, err
}
2020-06-13 11:18:11 +00:00
r = Revision{FullName: fullName}
2020-06-12 16:22:02 +00:00
err = json.Unmarshal(mJsonContents, &r)
if err != nil {
fmt.Println(fullPath, ">\tError:", err)
return r, err
}
// Now, let's fill in t.txt path
r.TextPath = filepath.Join(fullPath, "t.txt")
// There's sense in reading binary file only if the hypha is marked as such
if r.MimeType != "application/x-hypha" {
// Do not check for binary file presence, attempt to read it will fail anyway
if bPresent {
r.BinaryPath = filepath.Join(fullPath, "b")
2020-06-13 11:18:11 +00:00
r.BinaryRequest = fmt.Sprintf("%s?rev=%d&action=getBinary", r.FullName, r.Id)
2020-06-12 16:22:02 +00:00
} else {
return r, errors.New("makeRevision: b file not present")
}
}
// So far, so good. Let's fill in id. It is guaranteed to be correct, so no error checking
id, _ := strconv.Atoi(filepath.Base(fullPath))
r.Id = id
// It is safe now to return, I guess
return r, nil
}