prepare fs for eventual inclusion of user repos

This commit is contained in:
Massaki Archambault 2020-12-28 22:51:23 -05:00
parent 2063df8920
commit 4aca123c98
8 changed files with 194 additions and 50 deletions

View File

@ -1,28 +0,0 @@
package fs
import (
"fmt"
"github.com/badjware/gitlabfs/git"
"github.com/badjware/gitlabfs/gitlab"
"github.com/hanwen/go-fuse/v2/fs"
)
func Start(gf gitlab.GroupFetcher, gp git.GitClonerPuller, mountpoint string, rootGrouptID int) error {
fmt.Printf("Mounting in %v\n", mountpoint)
opts := &fs.Options{}
opts.Debug = true
root, err := newRootGroupNode(gf, gp, rootGrouptID)
if err != nil {
return fmt.Errorf("root group fetch fail: %v", err)
}
server, err := fs.Mount(mountpoint, root, opts)
if err != nil {
return fmt.Errorf("mount failed: %v", err)
}
server.Wait()
return nil
}

View File

@ -4,8 +4,6 @@ import (
"context"
"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"
@ -13,9 +11,8 @@ import (
type groupNode struct {
fs.Inode
param *FSParam
group *gitlab.Group
gf gitlab.GroupFetcher
gcp git.GitClonerPuller
}
// Ensure we are implementing the NodeReaddirer interface
@ -24,30 +21,28 @@ var _ = (fs.NodeReaddirer)((*groupNode)(nil))
// Ensure we are implementing the NodeLookuper interface
var _ = (fs.NodeLookuper)((*groupNode)(nil))
func newRootGroupNode(gf gitlab.GroupFetcher, gcp git.GitClonerPuller, gid int) (*groupNode, error) {
group, err := gf.FetchGroup(gid)
func newRootGroupNode(gid int, param *FSParam) (*groupNode, error) {
group, err := param.Gf.FetchGroup(gid)
if err != nil {
return nil, err
}
node := &groupNode{
param: param,
group: group,
gf: gf,
gcp: gcp,
}
return node, nil
}
func newGroupNode(gf gitlab.GroupFetcher, gcp git.GitClonerPuller, group *gitlab.Group) (*groupNode, error) {
func newGroupNode(group *gitlab.Group, param *FSParam) (*groupNode, error) {
node := &groupNode{
param: param,
group: group,
gf: gf,
gcp: gcp,
}
return node, nil
}
func (n *groupNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
groupContent, _ := n.gf.FetchGroupContent(n.group)
groupContent, _ := n.param.Gf.FetchGroupContent(n.group)
entries := make([]fuse.DirEntry, 0, len(groupContent.Groups)+len(groupContent.Repositories))
for _, group := range groupContent.Groups {
entries = append(entries, fuse.DirEntry{
@ -67,7 +62,7 @@ func (n *groupNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
}
func (n *groupNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fs.Inode, syscall.Errno) {
groupContent, _ := n.gf.FetchGroupContent(n.group)
groupContent, _ := n.param.Gf.FetchGroupContent(n.group)
// Check if the map of groups contains it
group, ok := groupContent.Groups[name]
@ -76,7 +71,7 @@ func (n *groupNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
Ino: uint64(group.ID),
Mode: fuse.S_IFDIR,
}
groupNode, _ := newGroupNode(n.gf, n.gcp, group)
groupNode, _ := newGroupNode(group, n.param)
return n.NewInode(ctx, groupNode, attrs), 0
}
@ -87,7 +82,7 @@ func (n *groupNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
Ino: uint64(repository.ID),
Mode: fuse.S_IFLNK,
}
repositoryNode, _ := newRepositoryNode(n.gcp, repository)
repositoryNode, _ := newRepositoryNode(repository, n.param)
return n.NewInode(ctx, repositoryNode, attrs), 0
}
return nil, syscall.ENOENT

44
fs/projects.go Normal file
View File

@ -0,0 +1,44 @@
package fs
import (
"context"
"fmt"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
)
type projectsNode struct {
fs.Inode
param *FSParam
rootGroupIds []int
}
// Ensure we are implementing the NodeOnAdder interface
var _ = (fs.NodeOnAdder)((*projectsNode)(nil))
func NewProjectsNode(rootGroupIds []int, param *FSParam) *projectsNode {
return &projectsNode{
param: param,
rootGroupIds: rootGroupIds,
}
}
func (n *projectsNode) OnAdd(ctx context.Context) {
for _, groupID := range n.rootGroupIds {
groupNode, err := newRootGroupNode(groupID, n.param)
if err != nil {
fmt.Printf("root group fetch fail: %v\n", err)
}
inode := n.NewPersistentInode(
ctx,
groupNode,
fs.StableAttr{
Ino: <-n.param.staticInoChan,
Mode: fuse.S_IFDIR,
},
)
n.AddChild(groupNode.group.Path, inode, false)
}
}

View File

@ -4,26 +4,24 @@ import (
"context"
"syscall"
"github.com/badjware/gitlabfs/git"
"github.com/badjware/gitlabfs/gitlab"
"github.com/hanwen/go-fuse/v2/fs"
)
type RepositoryNode struct {
fs.Inode
param *FSParam
repository *gitlab.Repository
gcp git.GitClonerPuller
}
// Ensure we are implementing the NodeReaddirer interface
var _ = (fs.NodeReadlinker)((*RepositoryNode)(nil))
func newRepositoryNode(gcp git.GitClonerPuller, repository *gitlab.Repository) (*RepositoryNode, error) {
func newRepositoryNode(repository *gitlab.Repository, param *FSParam) (*RepositoryNode, error) {
node := &RepositoryNode{
param: param,
repository: repository,
gcp: gcp,
}
// Passthrough the error if there is one, nothing to add here
// Errors on clone/pull are non-fatal
@ -32,7 +30,7 @@ func newRepositoryNode(gcp git.GitClonerPuller, repository *gitlab.Repository) (
func (n *RepositoryNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
// Create the local copy of the repo
localRepoLoc, _ := n.gcp.CloneOrPull(n.repository.CloneURL, n.repository.ID, "master")
localRepoLoc, _ := n.param.Gcp.CloneOrPull(n.repository.CloneURL, n.repository.ID, "master")
return []byte(localRepoLoc), 0
}

92
fs/root.go Normal file
View File

@ -0,0 +1,92 @@
package fs
import (
"context"
"fmt"
"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
)
type FSParam struct {
Gf gitlab.GroupFetcher
Gcp git.GitClonerPuller
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) {
projectsInode := n.NewPersistentInode(
ctx,
NewProjectsNode(
n.rootGroupIds,
n.param,
),
fs.StableAttr{
Ino: <-n.param.staticInoChan,
Mode: fuse.S_IFDIR,
},
)
n.AddChild("projects", projectsInode, false)
usersInode := n.NewPersistentInode(
ctx,
NewUsersNode(
n.userIds,
n.param,
),
fs.StableAttr{
Ino: <-n.param.staticInoChan,
Mode: fuse.S_IFDIR,
},
)
n.AddChild("users", usersInode, false)
}
func Start(mountpoint string, rootGroupIds []int, userIds []int, param *FSParam) error {
fmt.Printf("Mounting in %v\n", mountpoint)
opts := &fs.Options{}
opts.Debug = true
param.staticInoChan = make(chan uint64)
root := &rootNode{
param: param,
rootGroupIds: rootGroupIds,
userIds: userIds,
}
go staticInoGenerator(root.param.staticInoChan)
server, err := fs.Mount(mountpoint, root, opts)
if err != nil {
return fmt.Errorf("mount failed: %v", err)
}
server.Wait()
return nil
}
func staticInoGenerator(staticInoChan chan<- uint64) {
i := staticInodeStart
for {
staticInoChan <- i
i++
}
}

42
fs/users.go Normal file
View File

@ -0,0 +1,42 @@
package fs
import (
"context"
"github.com/hanwen/go-fuse/v2/fs"
)
type usersNode struct {
fs.Inode
param *FSParam
userIds []int
}
// Ensure we are implementing the NodeOnAdder interface
var _ = (fs.NodeOnAdder)((*usersNode)(nil))
func NewUsersNode(userIds []int, param *FSParam) *usersNode {
return &usersNode{
param: param,
userIds: userIds,
}
}
func (n *usersNode) OnAdd(ctx context.Context) {
// for _, userId := range n.userIds {
// userNode, err := newRootUserNode(userId, n.param)
// if err != nil {
// fmt.Printf("user fetch fail: %v\n", err)
// }
// inode := n.NewPersistentInode(
// ctx,
// userNode,
// fs.StableAttr{
// Ino: <-n.param.staticInoChan,
// Mode: fuse.S_IFDIR,
// },
// )
// n.AddChild(userNode.user.Path, inode, false)
// }
}

View File

@ -127,5 +127,6 @@ func (c *gitClient) pull(gpp *gitClonePullParam) error {
// Check if the local repo is on default branch
// Check if the local repo is dirty
// Checkout the remote default branch
// TODO
return nil
}

View File

@ -45,5 +45,5 @@ func main() {
gitClient, _ := git.NewClient(gitClientParam)
// Start the filesystem
fs.Start(gitlabClient, gitClient, mountpoint, *gitlabRootGroupID)
fs.Start(mountpoint, []int{*gitlabRootGroupID}, []int{}, &fs.FSParam{Gf: gitlabClient, Gcp: gitClient})
}