gitforgefs/fstree/root.go

108 lines
2.3 KiB
Go
Raw Normal View History

package fstree
import (
"context"
"fmt"
2024-06-06 05:51:34 +00:00
"log/slog"
2021-03-22 01:45:59 +00:00
"os"
"os/signal"
"syscall"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
)
2020-12-31 20:00:10 +00:00
type staticNode interface {
fs.InodeEmbedder
Ino() uint64
Mode() uint32
}
type GitClient interface {
FetchLocalRepositoryPath(source RepositorySource) (string, error)
}
2024-08-05 01:45:51 +00:00
type GitForge interface {
FetchRootGroupContent() (map[string]GroupSource, error)
FetchGroupContent(gid uint64) (map[string]GroupSource, map[string]RepositorySource, error)
}
type FSParam struct {
2024-08-05 01:45:51 +00:00
GitClient GitClient
GitForge GitForge
logger *slog.Logger
}
type rootNode struct {
fs.Inode
param *FSParam
}
var _ = (fs.NodeOnAdder)((*rootNode)(nil))
2024-06-06 05:51:34 +00:00
func Start(logger *slog.Logger, mountpoint string, mountoptions []string, param *FSParam, debug bool) error {
logger.Info("Mounting", "mountpoint", mountpoint)
opts := &fs.Options{}
opts.MountOptions.Options = mountoptions
2020-12-30 23:00:37 +00:00
opts.Debug = debug
2024-06-06 05:51:34 +00:00
param.logger = logger
root := &rootNode{
param: param,
}
server, err := fs.Mount(mountpoint, root, opts)
if err != nil {
return fmt.Errorf("mount failed: %v", err)
}
2021-03-22 01:45:59 +00:00
signalChan := make(chan os.Signal)
2024-06-06 05:51:34 +00:00
go signalHandler(logger, signalChan, server)
2021-03-22 01:45:59 +00:00
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
2021-03-24 02:56:16 +00:00
// server.Serve() is already called in fs.Mount() so we shouldn't call it ourself. We wait for the server to terminate.
server.Wait()
return nil
}
func (n *rootNode) OnAdd(ctx context.Context) {
2024-08-05 01:45:51 +00:00
rootGroups, err := n.param.GitForge.FetchRootGroupContent()
if err != nil {
panic(err)
}
for groupName, group := range rootGroups {
groupNode, _ := newGroupNodeFromSource(group, n.param)
persistentInode := n.NewPersistentInode(
ctx,
groupNode,
fs.StableAttr{
2024-08-09 20:34:45 +00:00
Ino: group.GetGroupID() + groupBaseInode,
Mode: fuse.S_IFDIR,
},
)
n.AddChild(groupName, persistentInode, false)
}
2024-06-06 05:51:34 +00:00
n.param.logger.Info("Mounted and ready to use")
}
2024-06-06 05:51:34 +00:00
func signalHandler(logger *slog.Logger, signalChan <-chan os.Signal, server *fuse.Server) {
2021-03-24 02:56:16 +00:00
err := server.WaitMount()
if err != nil {
2024-06-06 05:51:34 +00:00
logger.Error("failed to start exit signal handler", "error", err)
2021-03-24 02:56:16 +00:00
return
}
2021-03-22 01:45:59 +00:00
for {
s := <-signalChan
2024-06-06 05:51:34 +00:00
logger.Info("Caught signal", "signal", s)
2021-03-22 01:45:59 +00:00
err := server.Unmount()
if err != nil {
2024-06-06 05:51:34 +00:00
logger.Error("Failed to unmount", "error", err)
2021-03-22 01:45:59 +00:00
}
}
}