prepare fs for eventual inclusion of user repos
This commit is contained in:
parent
2063df8920
commit
4aca123c98
|
@ -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
|
|
||||||
}
|
|
25
fs/group.go
25
fs/group.go
|
@ -4,8 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/badjware/gitlabfs/git"
|
|
||||||
|
|
||||||
"github.com/badjware/gitlabfs/gitlab"
|
"github.com/badjware/gitlabfs/gitlab"
|
||||||
"github.com/hanwen/go-fuse/v2/fs"
|
"github.com/hanwen/go-fuse/v2/fs"
|
||||||
"github.com/hanwen/go-fuse/v2/fuse"
|
"github.com/hanwen/go-fuse/v2/fuse"
|
||||||
|
@ -13,9 +11,8 @@ import (
|
||||||
|
|
||||||
type groupNode struct {
|
type groupNode struct {
|
||||||
fs.Inode
|
fs.Inode
|
||||||
|
param *FSParam
|
||||||
group *gitlab.Group
|
group *gitlab.Group
|
||||||
gf gitlab.GroupFetcher
|
|
||||||
gcp git.GitClonerPuller
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we are implementing the NodeReaddirer interface
|
// Ensure we are implementing the NodeReaddirer interface
|
||||||
|
@ -24,30 +21,28 @@ var _ = (fs.NodeReaddirer)((*groupNode)(nil))
|
||||||
// Ensure we are implementing the NodeLookuper interface
|
// Ensure we are implementing the NodeLookuper interface
|
||||||
var _ = (fs.NodeLookuper)((*groupNode)(nil))
|
var _ = (fs.NodeLookuper)((*groupNode)(nil))
|
||||||
|
|
||||||
func newRootGroupNode(gf gitlab.GroupFetcher, gcp git.GitClonerPuller, gid int) (*groupNode, error) {
|
func newRootGroupNode(gid int, param *FSParam) (*groupNode, error) {
|
||||||
group, err := gf.FetchGroup(gid)
|
group, err := param.Gf.FetchGroup(gid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
node := &groupNode{
|
node := &groupNode{
|
||||||
|
param: param,
|
||||||
group: group,
|
group: group,
|
||||||
gf: gf,
|
|
||||||
gcp: gcp,
|
|
||||||
}
|
}
|
||||||
return node, nil
|
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{
|
node := &groupNode{
|
||||||
|
param: param,
|
||||||
group: group,
|
group: group,
|
||||||
gf: gf,
|
|
||||||
gcp: gcp,
|
|
||||||
}
|
}
|
||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *groupNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
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))
|
entries := make([]fuse.DirEntry, 0, len(groupContent.Groups)+len(groupContent.Repositories))
|
||||||
for _, group := range groupContent.Groups {
|
for _, group := range groupContent.Groups {
|
||||||
entries = append(entries, fuse.DirEntry{
|
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) {
|
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
|
// Check if the map of groups contains it
|
||||||
group, ok := groupContent.Groups[name]
|
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),
|
Ino: uint64(group.ID),
|
||||||
Mode: fuse.S_IFDIR,
|
Mode: fuse.S_IFDIR,
|
||||||
}
|
}
|
||||||
groupNode, _ := newGroupNode(n.gf, n.gcp, group)
|
groupNode, _ := newGroupNode(group, n.param)
|
||||||
return n.NewInode(ctx, groupNode, attrs), 0
|
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),
|
Ino: uint64(repository.ID),
|
||||||
Mode: fuse.S_IFLNK,
|
Mode: fuse.S_IFLNK,
|
||||||
}
|
}
|
||||||
repositoryNode, _ := newRepositoryNode(n.gcp, repository)
|
repositoryNode, _ := newRepositoryNode(repository, n.param)
|
||||||
return n.NewInode(ctx, repositoryNode, attrs), 0
|
return n.NewInode(ctx, repositoryNode, attrs), 0
|
||||||
}
|
}
|
||||||
return nil, syscall.ENOENT
|
return nil, syscall.ENOENT
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,26 +4,24 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/badjware/gitlabfs/git"
|
|
||||||
"github.com/badjware/gitlabfs/gitlab"
|
"github.com/badjware/gitlabfs/gitlab"
|
||||||
"github.com/hanwen/go-fuse/v2/fs"
|
"github.com/hanwen/go-fuse/v2/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RepositoryNode struct {
|
type RepositoryNode struct {
|
||||||
fs.Inode
|
fs.Inode
|
||||||
|
param *FSParam
|
||||||
repository *gitlab.Repository
|
repository *gitlab.Repository
|
||||||
|
|
||||||
gcp git.GitClonerPuller
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we are implementing the NodeReaddirer interface
|
// Ensure we are implementing the NodeReaddirer interface
|
||||||
var _ = (fs.NodeReadlinker)((*RepositoryNode)(nil))
|
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{
|
node := &RepositoryNode{
|
||||||
|
param: param,
|
||||||
repository: repository,
|
repository: repository,
|
||||||
gcp: gcp,
|
|
||||||
}
|
}
|
||||||
// Passthrough the error if there is one, nothing to add here
|
// Passthrough the error if there is one, nothing to add here
|
||||||
// Errors on clone/pull are non-fatal
|
// 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) {
|
func (n *RepositoryNode) Readlink(ctx context.Context) ([]byte, syscall.Errno) {
|
||||||
// Create the local copy of the repo
|
// 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
|
return []byte(localRepoLoc), 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -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++
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
// }
|
||||||
|
}
|
|
@ -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 on default branch
|
||||||
// Check if the local repo is dirty
|
// Check if the local repo is dirty
|
||||||
// Checkout the remote default branch
|
// Checkout the remote default branch
|
||||||
|
// TODO
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -45,5 +45,5 @@ func main() {
|
||||||
gitClient, _ := git.NewClient(gitClientParam)
|
gitClient, _ := git.NewClient(gitClientParam)
|
||||||
|
|
||||||
// Start the filesystem
|
// Start the filesystem
|
||||||
fs.Start(gitlabClient, gitClient, mountpoint, *gitlabRootGroupID)
|
fs.Start(mountpoint, []int{*gitlabRootGroupID}, []int{}, &fs.FSParam{Gf: gitlabClient, Gcp: gitClient})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue