gitforgefs/fs/root.go

130 lines
2.4 KiB
Go
Raw Normal View History

package fs
import (
"context"
"fmt"
2021-03-22 01:45:59 +00:00
"os"
"os/signal"
"syscall"
"github.com/badjware/gitlabfs/git"
"github.com/badjware/gitlabfs/gitlab"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
)
const (
staticInodeStart = uint64(int(^(uint(0))>>1)) + 1
)
2020-12-31 20:00:10 +00:00
type staticNode interface {
fs.InodeEmbedder
Ino() uint64
Mode() uint32
}
type FSParam struct {
2020-12-30 00:49:11 +00:00
Git git.GitClonerPuller
2020-12-30 23:00:37 +00:00
Gitlab gitlab.GitlabFetcher
RootGroupIds []int
UserIds []int
staticInoChan chan uint64
}
type rootNode struct {
fs.Inode
param *FSParam
rootGroupIds []int
userIds []int
}
var _ = (fs.NodeOnAdder)((*rootNode)(nil))
func (n *rootNode) OnAdd(ctx context.Context) {
2021-03-03 05:34:32 +00:00
groupsInode := n.NewPersistentInode(
ctx,
2021-03-03 05:34:32 +00:00
newGroupsNode(
n.rootGroupIds,
n.param,
),
fs.StableAttr{
Ino: <-n.param.staticInoChan,
Mode: fuse.S_IFDIR,
},
)
2021-03-03 05:34:32 +00:00
n.AddChild("groups", groupsInode, false)
usersInode := n.NewPersistentInode(
ctx,
2020-12-30 00:49:11 +00:00
newUsersNode(
n.userIds,
n.param,
),
fs.StableAttr{
Ino: <-n.param.staticInoChan,
Mode: fuse.S_IFDIR,
},
)
n.AddChild("users", usersInode, false)
2020-12-30 23:00:37 +00:00
fmt.Println("Mounted and ready to use")
}
func Start(mountpoint string, mountoptions []string, param *FSParam, debug bool) error {
fmt.Printf("Mounting in %v\n", mountpoint)
opts := &fs.Options{}
opts.MountOptions.Options = mountoptions
2020-12-30 23:00:37 +00:00
opts.Debug = debug
param.staticInoChan = make(chan uint64)
root := &rootNode{
param: param,
rootGroupIds: param.RootGroupIds,
userIds: param.UserIds,
}
go staticInoGenerator(root.param.staticInoChan)
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)
go signalHandler(signalChan, server)
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 staticInoGenerator(staticInoChan chan<- uint64) {
i := staticInodeStart
for {
staticInoChan <- i
i++
}
}
2021-03-22 01:45:59 +00:00
func signalHandler(signalChan <-chan os.Signal, server *fuse.Server) {
2021-03-24 02:56:16 +00:00
err := server.WaitMount()
if err != nil {
fmt.Printf("failed to start exit signal handler: %v\n", err)
return
}
2021-03-22 01:45:59 +00:00
for {
s := <-signalChan
fmt.Printf("Caught %v: stopping\n", s)
err := server.Unmount()
if err != nil {
fmt.Printf("Failed to unmount: %v\n", err)
}
}
}