split store constructors into own files: tools.go, root.go
This commit is contained in:
parent
46c025b594
commit
6b1ba9a998
|
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"ollie/pkg/backend"
|
||||
"ollie/pkg/paths"
|
||||
"olliesrv/store"
|
||||
)
|
||||
|
||||
// NewRootStore returns a read-only Store for synthetic root-level files.
|
||||
func NewRootStore() *store.DirStore {
|
||||
helpPath := paths.CfgDir() + "/help.md"
|
||||
entries := map[string]func() ([]byte, error){
|
||||
"backends": func() ([]byte, error) {
|
||||
return []byte(strings.Join(backend.Backends(), "\n") + "\n"), nil
|
||||
},
|
||||
"help": func() ([]byte, error) {
|
||||
return os.ReadFile(helpPath)
|
||||
},
|
||||
}
|
||||
notBlocking := func(context.Context, string) ([]byte, string, error) {
|
||||
return nil, "", fmt.Errorf("blocking read not supported")
|
||||
}
|
||||
readOnly := func([]byte) error { return fmt.Errorf("read-only") }
|
||||
|
||||
return store.NewDirStore(nil, 0444,
|
||||
store.WithReadOnly(),
|
||||
store.WithResolver(func(_ []string, name string) (string, error) {
|
||||
if _, ok := entries[name]; ok {
|
||||
return name, nil
|
||||
}
|
||||
return "", fmt.Errorf("%s: not found", name)
|
||||
}),
|
||||
store.WithLister(func(_ []string) ([]os.DirEntry, error) {
|
||||
return []os.DirEntry{
|
||||
syntheticEntry("backends", 0444),
|
||||
syntheticEntry("help", 0444),
|
||||
}, nil
|
||||
}),
|
||||
store.WithOpener(func(_ []string, name string) (StoreEntry, error) {
|
||||
readFn, ok := entries[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s: not found", name)
|
||||
}
|
||||
return &store.EntryConfig{
|
||||
StatFn: func() (os.FileInfo, error) { return &syntheticFileInfo{Name_: name, Mode_: 0444}, nil },
|
||||
ReadFn: readFn,
|
||||
WriteFn: readOnly,
|
||||
BlockingReadFn: notBlocking,
|
||||
}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
90
server.go
90
server.go
|
|
@ -42,96 +42,6 @@ func syntheticDirEntry(name string, mode os.FileMode) os.DirEntry {
|
|||
return store.DirEntry(name, mode)
|
||||
}
|
||||
|
||||
// toolIndex generates a tool index from a store's file listing.
|
||||
func toolIndex(s Store) ([]byte, error) {
|
||||
entries, err := s.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var sb strings.Builder
|
||||
for _, e := range entries {
|
||||
if e.IsDir() || e.Name() == "idx" {
|
||||
continue
|
||||
}
|
||||
entry, err := s.Open(e.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
data, err := entry.Read()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var desc, args string
|
||||
for line := range strings.SplitSeq(string(data), "\n") {
|
||||
if d, ok := strings.CutPrefix(line, "# description:"); ok {
|
||||
desc = strings.TrimSpace(d)
|
||||
} else if a, ok := strings.CutPrefix(line, "# Args:"); ok {
|
||||
args = strings.TrimSpace(a)
|
||||
} else if a, ok := strings.CutPrefix(line, "# args:"); ok {
|
||||
args = strings.TrimSpace(a)
|
||||
}
|
||||
if !strings.HasPrefix(line, "#") && line != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
if desc == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(&sb, "## %s\n", e.Name())
|
||||
fmt.Fprintf(&sb, "description: %s\n", desc)
|
||||
if args != "" {
|
||||
fmt.Fprintf(&sb, "args: %s\n", args)
|
||||
}
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
return []byte(sb.String()), nil
|
||||
}
|
||||
|
||||
// NewRootStore returns a read-only Store for synthetic root-level files.
|
||||
func NewRootStore() *store.DirStore {
|
||||
helpPath := paths.CfgDir() + "/help.md"
|
||||
entries := map[string]func() ([]byte, error){
|
||||
"backends": func() ([]byte, error) {
|
||||
return []byte(strings.Join(backend.Backends(), "\n") + "\n"), nil
|
||||
},
|
||||
"help": func() ([]byte, error) {
|
||||
return os.ReadFile(helpPath)
|
||||
},
|
||||
}
|
||||
notBlocking := func(context.Context, string) ([]byte, string, error) {
|
||||
return nil, "", fmt.Errorf("blocking read not supported")
|
||||
}
|
||||
readOnly := func([]byte) error { return fmt.Errorf("read-only") }
|
||||
|
||||
return store.NewDirStore(nil, 0444,
|
||||
store.WithReadOnly(),
|
||||
store.WithResolver(func(_ []string, name string) (string, error) {
|
||||
if _, ok := entries[name]; ok {
|
||||
return name, nil // virtual path, handled by opener
|
||||
}
|
||||
return "", fmt.Errorf("%s: not found", name)
|
||||
}),
|
||||
store.WithLister(func(_ []string) ([]os.DirEntry, error) {
|
||||
return []os.DirEntry{
|
||||
syntheticEntry("backends", 0444),
|
||||
syntheticEntry("help", 0444),
|
||||
}, nil
|
||||
}),
|
||||
store.WithOpener(func(_ []string, name string) (StoreEntry, error) {
|
||||
readFn, ok := entries[name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s: not found", name)
|
||||
}
|
||||
return &store.EntryConfig{
|
||||
StatFn: func() (os.FileInfo, error) { return &syntheticFileInfo{Name_: name, Mode_: 0444}, nil },
|
||||
ReadFn: readFn,
|
||||
WriteFn: readOnly,
|
||||
BlockingReadFn: notBlocking,
|
||||
}, nil
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
const (
|
||||
QTDir = plan9.QTDIR
|
||||
QTFile = plan9.QTFILE
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// toolIndex generates a tool index from a store's file listing.
|
||||
func toolIndex(s Store) ([]byte, error) {
|
||||
entries, err := s.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var sb strings.Builder
|
||||
for _, e := range entries {
|
||||
if e.IsDir() || e.Name() == "idx" {
|
||||
continue
|
||||
}
|
||||
entry, err := s.Open(e.Name())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
data, err := entry.Read()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var desc, args string
|
||||
for line := range strings.SplitSeq(string(data), "\n") {
|
||||
if d, ok := strings.CutPrefix(line, "# description:"); ok {
|
||||
desc = strings.TrimSpace(d)
|
||||
} else if a, ok := strings.CutPrefix(line, "# Args:"); ok {
|
||||
args = strings.TrimSpace(a)
|
||||
} else if a, ok := strings.CutPrefix(line, "# args:"); ok {
|
||||
args = strings.TrimSpace(a)
|
||||
}
|
||||
if !strings.HasPrefix(line, "#") && line != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
if desc == "" {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(&sb, "## %s\n", e.Name())
|
||||
fmt.Fprintf(&sb, "description: %s\n", desc)
|
||||
if args != "" {
|
||||
fmt.Fprintf(&sb, "args: %s\n", args)
|
||||
}
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
return []byte(sb.String()), nil
|
||||
}
|
||||
Reference in New Issue