mesh/delivery-group group feat/sdk1 rejected: composed together: the checker's verdict at the members' heads (428d048dd50a): unit: git.novox.be/novox/mesh-sdk/…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: unit: git.novox.be/novox/mesh-sdk/go/process.TestStatePutWritesAKeyWhole: a Put through a short blackout: 0, mesh-mail's state send…
Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
67 lines
2.3 KiB
Go
67 lines
2.3 KiB
Go
package catalogue
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// PlacedDataItem is one data item a module on a node declares, as placed on that node.
|
|
type PlacedDataItem struct {
|
|
Module string `json:"module"`
|
|
ID string `json:"item"`
|
|
Class string `json:"class"`
|
|
// Path is the item's place on the node; CoveredBy the path whose snapshot keeps it (the item, or the item its dump
|
|
// writes into), empty when it is not backed up.
|
|
Path string `json:"path"`
|
|
CoveredBy string `json:"covered_by,omitempty"`
|
|
// Protection is backup, redundancy, both or none; Measure walk, dataset or shallow.
|
|
Protection string `json:"protection,omitempty"`
|
|
Measure string `json:"measure,omitempty"`
|
|
}
|
|
|
|
var (
|
|
dataModuleHeader = regexp.MustCompile(`^#\s*([a-z0-9][a-z0-9-]*)$`)
|
|
dataSafePath = regexp.MustCompile(`^/[^\s'"\\$` + "`" + `]*$`)
|
|
)
|
|
|
|
// ParseDataItems reads the node-backup holder's data text (`${backup:data}`: a `# <module>` line, then one line per item,
|
|
// `item <id> <class> <path> <covered-by or -> <protection> <measure>`) into each module's items, in order. A line it does
|
|
// not read is refused, naming the module: a path with a space or a quote is never handed to a measuring shell.
|
|
func ParseDataItems(text string) (map[string][]PlacedDataItem, error) {
|
|
out := map[string][]PlacedDataItem{}
|
|
module := ""
|
|
for _, raw := range strings.Split(text, "\n") {
|
|
line := strings.TrimSpace(raw)
|
|
if line == "" {
|
|
continue
|
|
}
|
|
if m := dataModuleHeader.FindStringSubmatch(line); m != nil {
|
|
module = m[1]
|
|
continue
|
|
}
|
|
if strings.HasPrefix(line, "#") || module == "" {
|
|
continue
|
|
}
|
|
f := strings.Fields(line)
|
|
if len(f) < 5 || len(f) > 7 || f[0] != "item" || !dataSafePath.MatchString(f[3]) || (f[4] != "-" && !dataSafePath.MatchString(f[4])) {
|
|
return nil, fmt.Errorf("%s declares a data line that is not read: %s", module, line)
|
|
}
|
|
it := PlacedDataItem{Module: module, ID: f[1], Class: f[2], Path: f[3], Measure: MeasureWalk}
|
|
if len(f) >= 6 {
|
|
it.Protection = f[5]
|
|
}
|
|
if len(f) == 7 {
|
|
it.Measure = f[6]
|
|
}
|
|
if it.Measure != MeasureWalk && it.Measure != MeasureDataset && it.Measure != MeasureShallow {
|
|
return nil, fmt.Errorf("%s declares a data line that is not read: %s", module, line)
|
|
}
|
|
if f[4] != "-" {
|
|
it.CoveredBy = f[4]
|
|
}
|
|
out[module] = append(out[module], it)
|
|
}
|
|
return out, nil
|
|
}
|