feat: xmnt
This commit is contained in:
parent
00b3e4b24f
commit
5a998b713c
16 changed files with 1481 additions and 0 deletions
68
mnt/mnt.go
Normal file
68
mnt/mnt.go
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package mnt
|
||||
|
||||
import (
|
||||
"github.com/go-errors/errors"
|
||||
|
||||
"gensokyo.cafe/xmnt/msg"
|
||||
)
|
||||
|
||||
type Mounter interface {
|
||||
Mount() error
|
||||
Unmount() error
|
||||
}
|
||||
|
||||
type (
|
||||
MounterFunc func(*Preset) (Mounter, error)
|
||||
MatcherFunc func(string) ([]*Preset, error)
|
||||
)
|
||||
|
||||
var mounters = map[string]MounterFunc{}
|
||||
|
||||
func RegisterMounter(typeName string, fn MounterFunc) {
|
||||
mounters[typeName] = fn
|
||||
}
|
||||
|
||||
func MounterFromPreset(preset *Preset) (Mounter, error) {
|
||||
if fn, ok := mounters[preset.Type]; !ok {
|
||||
return nil, errors.Errorf("unknown type %q", preset.Type)
|
||||
} else {
|
||||
return fn(preset)
|
||||
}
|
||||
}
|
||||
|
||||
var matchers []MatcherFunc
|
||||
|
||||
func RegisterMatcher(fn MatcherFunc) {
|
||||
matchers = append(matchers, fn)
|
||||
}
|
||||
|
||||
func MatchAll(s string) ([]*Preset, error) {
|
||||
// Match against presets. If matched, return the preset (should be only one).
|
||||
if matches, err := match(s); err != nil {
|
||||
msg.Errorf("Failed to find match in presets: %v", err)
|
||||
} else if len(matches) > 0 {
|
||||
return matches[:1], nil
|
||||
}
|
||||
|
||||
// Run other matchers. Might produce multiple matches.
|
||||
var ret []*Preset
|
||||
rCh := make(chan []*Preset, 1)
|
||||
|
||||
for _, fn := range matchers {
|
||||
go func(fn MatcherFunc) {
|
||||
matches, err := fn(s)
|
||||
if err != nil {
|
||||
msg.Errorf("%v", err)
|
||||
rCh <- nil
|
||||
} else {
|
||||
rCh <- matches
|
||||
}
|
||||
}(fn)
|
||||
}
|
||||
for range matchers {
|
||||
matches := <-rCh
|
||||
ret = append(ret, matches...)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
97
mnt/preset.go
Normal file
97
mnt/preset.go
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
package mnt
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/go-errors/errors"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"gensokyo.cafe/xmnt/msg"
|
||||
"gensokyo.cafe/xmnt/util"
|
||||
)
|
||||
|
||||
type Preset struct {
|
||||
Name string `yaml:"name"`
|
||||
Type string `yaml:"type"`
|
||||
Path string `yaml:"path"`
|
||||
MountPoint string `yaml:"mountpoint"`
|
||||
|
||||
AuthCmd string `yaml:"auth_cmd"` // e.g. for loading the encryption key
|
||||
MountCmd string `yaml:"mount_cmd"`
|
||||
CheckCmd string `yaml:"check_cmd"` // check if the mounting was successful
|
||||
|
||||
UnmountCmd string `yaml:"unmount_cmd"`
|
||||
UnAuthCmd string `yaml:"unauth_cmd"` // e.g. for unloading the encryption key
|
||||
UnmountCheckCmd string `yaml:"unmount_check_cmd"`
|
||||
}
|
||||
|
||||
func (p *Preset) String() string {
|
||||
return p.Type + ": " + p.Name + " (" + p.Path + ")"
|
||||
}
|
||||
|
||||
func readPreset(path string) (*Preset, error) {
|
||||
buf, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, 0)
|
||||
}
|
||||
var preset *Preset
|
||||
if err = yaml.Unmarshal(buf, &preset); err != nil {
|
||||
return nil, errors.Wrap(err, 0)
|
||||
}
|
||||
|
||||
if preset.Name == "" {
|
||||
preset.Name = filepath.Base(path)[:len(filepath.Base(path))-4] // remove .yml
|
||||
}
|
||||
return preset, nil
|
||||
}
|
||||
|
||||
func ReadPresets() ([]*Preset, error) {
|
||||
cfgDir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return nil, errors.WrapPrefix(err, "cannot obtain user config dir", 0)
|
||||
}
|
||||
|
||||
presetsDir := filepath.Join(cfgDir, "xmnt", "presets")
|
||||
dirExist, err := util.DirExists(presetsDir)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, 0)
|
||||
}
|
||||
if !dirExist {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var ret []*Preset
|
||||
|
||||
entries, err := os.ReadDir(presetsDir)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, 0)
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if !entry.Type().IsRegular() || !strings.HasSuffix(entry.Name(), ".yml") {
|
||||
continue
|
||||
}
|
||||
preset, err := readPreset(filepath.Join(presetsDir, entry.Name()))
|
||||
if err != nil {
|
||||
msg.Errorf("Failed to read preset %s: %v", entry.Name(), err)
|
||||
continue
|
||||
}
|
||||
ret = append(ret, preset)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func match(s string) ([]*Preset, error) {
|
||||
presets, err := ReadPresets()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, 0)
|
||||
}
|
||||
for _, p := range presets {
|
||||
// for presets, only return exact match.
|
||||
if p.Name == s {
|
||||
return []*Preset{p}, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue