add refresh "button"

This commit is contained in:
Massaki Archambault 2020-12-31 15:00:10 -05:00
parent 8d3f49061b
commit e43d9520f8
9 changed files with 142 additions and 5 deletions

View File

@ -12,7 +12,9 @@ import (
type groupNode struct {
fs.Inode
param *FSParam
group *gitlab.Group
group *gitlab.Group
staticNodes map[string]staticNode
}
// Ensure we are implementing the NodeReaddirer interface
@ -29,6 +31,9 @@ func newGroupNodeByID(gid int, param *FSParam) (*groupNode, error) {
node := &groupNode{
param: param,
group: group,
staticNodes: map[string]staticNode{
".refresh": newRefreshNode(group, param),
},
}
return node, nil
}
@ -37,13 +42,16 @@ func newGroupNode(group *gitlab.Group, param *FSParam) (*groupNode, error) {
node := &groupNode{
param: param,
group: group,
staticNodes: map[string]staticNode{
".refresh": newRefreshNode(group, param),
},
}
return node, nil
}
func (n *groupNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
groupContent, _ := n.param.Gitlab.FetchGroupContent(n.group)
entries := make([]fuse.DirEntry, 0, len(groupContent.Groups)+len(groupContent.Projects))
entries := make([]fuse.DirEntry, 0, len(groupContent.Groups)+len(groupContent.Projects)+len(n.staticNodes))
for _, group := range groupContent.Groups {
entries = append(entries, fuse.DirEntry{
Name: group.Name,
@ -58,6 +66,13 @@ func (n *groupNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
Mode: fuse.S_IFLNK,
})
}
for name, staticNode := range n.staticNodes {
entries = append(entries, fuse.DirEntry{
Name: name,
Ino: staticNode.Ino(),
Mode: staticNode.Mode(),
})
}
return fs.NewListDirStream(entries), 0
}
@ -85,5 +100,16 @@ func (n *groupNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
repositoryNode, _ := newRepositoryNode(project, n.param)
return n.NewInode(ctx, repositoryNode, attrs), 0
}
// Check if the map of static nodes contains it
staticNode, ok := n.staticNodes[name]
if ok {
attrs := fs.StableAttr{
Ino: staticNode.Ino(),
Mode: staticNode.Mode(),
}
return n.NewInode(ctx, staticNode, attrs), 0
}
return nil, syscall.ENOENT
}

46
fs/refresh.go Normal file
View File

@ -0,0 +1,46 @@
package fs
import (
"context"
"syscall"
"github.com/badjware/gitlabfs/gitlab"
"github.com/hanwen/go-fuse/v2/fs"
"github.com/hanwen/go-fuse/v2/fuse"
)
type refreshNode struct {
fs.Inode
ino uint64
refresher gitlab.Refresher
}
// Ensure we are implementing the NodeSetattrer interface
var _ = (fs.NodeSetattrer)((*refreshNode)(nil))
// Ensure we are implementing the NodeOpener interface
var _ = (fs.NodeOpener)((*refreshNode)(nil))
func newRefreshNode(refresher gitlab.Refresher, param *FSParam) *refreshNode {
return &refreshNode{
ino: <-param.staticInoChan,
refresher: refresher,
}
}
func (n *refreshNode) Ino() uint64 {
return n.ino
}
func (n *refreshNode) Mode() uint32 {
return fuse.S_IFREG
}
func (n *refreshNode) Setattr(ctx context.Context, fh fs.FileHandle, in *fuse.SetAttrIn, out *fuse.AttrOut) syscall.Errno {
return 0
}
func (n *refreshNode) Open(ctx context.Context, flags uint32) (fh fs.FileHandle, fuseFlags uint32, errno syscall.Errno) {
n.refresher.InvalidateCache()
return nil, 0, 0
}

View File

@ -18,7 +18,6 @@ type RepositoryNode struct {
var _ = (fs.NodeReadlinker)((*RepositoryNode)(nil))
func newRepositoryNode(project *gitlab.Project, param *FSParam) (*RepositoryNode, error) {
node := &RepositoryNode{
param: param,
project: project,

View File

@ -15,6 +15,12 @@ const (
staticInodeStart = uint64(int(^(uint(0))>>1)) + 1
)
type staticNode interface {
fs.InodeEmbedder
Ino() uint64
Mode() uint32
}
type FSParam struct {
Git git.GitClonerPuller
Gitlab gitlab.GitlabFetcher

View File

@ -71,7 +71,9 @@ func (n *usersNode) OnAdd(ctx context.Context) {
type userNode struct {
fs.Inode
param *FSParam
user *gitlab.User
user *gitlab.User
staticNodes map[string]staticNode
}
// Ensure we are implementing the NodeReaddirer interface
@ -88,6 +90,9 @@ func newUserNodeByID(uid int, param *FSParam) (*userNode, error) {
node := &userNode{
param: param,
user: user,
staticNodes: map[string]staticNode{
".refresh": newRefreshNode(user, param),
},
}
return node, nil
}
@ -96,13 +101,16 @@ func newUserNode(user *gitlab.User, param *FSParam) (*userNode, error) {
node := &userNode{
param: param,
user: user,
staticNodes: map[string]staticNode{
".refresh": newRefreshNode(user, param),
},
}
return node, nil
}
func (n *userNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
userContent, _ := n.param.Gitlab.FetchUserContent(n.user)
entries := make([]fuse.DirEntry, 0, len(userContent.Projects))
entries := make([]fuse.DirEntry, 0, len(userContent.Projects)+len(n.staticNodes))
for _, project := range userContent.Projects {
entries = append(entries, fuse.DirEntry{
Name: project.Name,
@ -110,11 +118,20 @@ func (n *userNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
Mode: fuse.S_IFLNK,
})
}
for name, staticNode := range n.staticNodes {
entries = append(entries, fuse.DirEntry{
Name: name,
Ino: staticNode.Ino(),
Mode: staticNode.Mode(),
})
}
return fs.NewListDirStream(entries), 0
}
func (n *userNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut) (*fs.Inode, syscall.Errno) {
userContent, _ := n.param.Gitlab.FetchUserContent(n.user)
// Check if the map of projects contains it
project, ok := userContent.Projects[name]
if ok {
attrs := fs.StableAttr{
@ -124,5 +141,16 @@ func (n *userNode) Lookup(ctx context.Context, name string, out *fuse.EntryOut)
repositoryNode, _ := newRepositoryNode(project, n.param)
return n.NewInode(ctx, repositoryNode, attrs), 0
}
// Check if the map of static nodes contains it
staticNode, ok := n.staticNodes[name]
if ok {
attrs := fs.StableAttr{
Ino: staticNode.Ino(),
Mode: staticNode.Mode(),
}
return n.NewInode(ctx, staticNode, attrs), 0
}
return nil, syscall.ENOENT
}

View File

@ -16,6 +16,10 @@ type GitlabFetcher interface {
UserFetcher
}
type Refresher interface {
InvalidateCache()
}
type GitlabClientParam struct {
PullMethod string
}

View File

@ -2,6 +2,7 @@ package gitlab
import (
"fmt"
"sync"
"github.com/xanzy/go-gitlab"
)
@ -20,6 +21,7 @@ type Group struct {
ID int
Name string
mux sync.Mutex
content *GroupContent
}
@ -31,6 +33,13 @@ func NewGroupFromGitlabGroup(group *gitlab.Group) Group {
}
}
func (g *Group) InvalidateCache() {
g.mux.Lock()
defer g.mux.Unlock()
g.content = nil
}
func (c *gitlabClient) FetchGroup(gid int) (*Group, error) {
gitlabGroup, _, err := c.client.Groups.GetGroup(gid)
if err != nil {
@ -41,6 +50,10 @@ func (c *gitlabClient) FetchGroup(gid int) (*Group, error) {
}
func (c *gitlabClient) FetchGroupContent(group *Group) (*GroupContent, error) {
group.mux.Lock()
defer group.mux.Unlock()
// Get cached data if available
if group.content != nil {
return group.content, nil
}

View File

@ -2,6 +2,7 @@ package gitlab
import (
"fmt"
"sync"
"github.com/xanzy/go-gitlab"
)
@ -20,6 +21,7 @@ type User struct {
ID int
Name string
mux sync.Mutex
content *UserContent
}
@ -31,6 +33,13 @@ func NewUserFromGitlabUser(user *gitlab.User) User {
}
}
func (u *User) InvalidateCache() {
u.mux.Lock()
defer u.mux.Unlock()
u.content = nil
}
func (c *gitlabClient) FetchUser(uid int) (*User, error) {
gitlabUser, _, err := c.client.Users.GetUser(uid)
if err != nil {
@ -50,6 +59,10 @@ func (c *gitlabClient) FetchCurrentUser() (*User, error) {
}
func (c *gitlabClient) FetchUserContent(user *User) (*UserContent, error) {
user.mux.Lock()
defer user.mux.Unlock()
// Get cached data if available
if user.content != nil {
return user.content, nil
}

2
go.sum
View File

@ -19,6 +19,7 @@ github.com/go-git/go-git v4.7.0+incompatible/go.mod h1:6+421e08gnZWn30y26Vchf7ef
github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2JgI=
github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
@ -96,6 +97,7 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqG
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI=
google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQk=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=