refactor to decouple fstree package from git package
This commit is contained in:
parent
0c647a692f
commit
735a803cdb
|
@ -42,7 +42,7 @@ func newGroupNodeFromSource(source GroupSource, param *FSParam) (*groupNode, err
|
||||||
func (n *groupNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
func (n *groupNode) Readdir(ctx context.Context) (fs.DirStream, syscall.Errno) {
|
||||||
groups, repositories, err := n.param.GitPlatform.FetchGroupContent(n.source.GetGroupID())
|
groups, repositories, err := n.param.GitPlatform.FetchGroupContent(n.source.GetGroupID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Errorf("%v", err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
entries := make([]fuse.DirEntry, 0, len(groups)+len(repositories)+len(n.staticNodes))
|
entries := make([]fuse.DirEntry, 0, len(groups)+len(repositories)+len(n.staticNodes))
|
||||||
|
|
|
@ -2,6 +2,7 @@ package fstree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/hanwen/go-fuse/v2/fs"
|
"github.com/hanwen/go-fuse/v2/fs"
|
||||||
|
@ -37,7 +38,9 @@ func newRepositoryNodeFromSource(source RepositorySource, param *FSParam) (*repo
|
||||||
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
|
||||||
// TODO: cleanup
|
// TODO: cleanup
|
||||||
localRepositoryPath, _ := n.param.GitImplementation.CloneOrPull(n.source.GetCloneURL(), int(n.source.GetRepositoryID()), n.source.GetDefaultBranch())
|
localRepositoryPath, err := n.param.GitClient.FetchLocalRepositoryPath(n.source)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
return []byte(localRepositoryPath), 0
|
return []byte(localRepositoryPath), 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/badjware/gitlabfs/git"
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
@ -22,13 +21,17 @@ type staticNode interface {
|
||||||
Mode() uint32
|
Mode() uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GitClient interface {
|
||||||
|
FetchLocalRepositoryPath(source RepositorySource) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
type GitPlatform interface {
|
type GitPlatform interface {
|
||||||
FetchRootGroupContent() (map[string]GroupSource, error)
|
FetchRootGroupContent() (map[string]GroupSource, error)
|
||||||
FetchGroupContent(gid uint64) (map[string]GroupSource, map[string]RepositorySource, error)
|
FetchGroupContent(gid uint64) (map[string]GroupSource, map[string]RepositorySource, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type FSParam struct {
|
type FSParam struct {
|
||||||
GitImplementation git.GitClonerPuller
|
GitClient GitClient
|
||||||
GitPlatform GitPlatform
|
GitPlatform GitPlatform
|
||||||
|
|
||||||
staticInoChan chan uint64
|
staticInoChan chan uint64
|
||||||
|
|
|
@ -2,39 +2,33 @@ package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/url"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/badjware/gitlabfs/fstree"
|
||||||
"github.com/vmihailenco/taskq/v3"
|
"github.com/vmihailenco/taskq/v3"
|
||||||
"github.com/vmihailenco/taskq/v3/memqueue"
|
"github.com/vmihailenco/taskq/v3/memqueue"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
CloneInit = iota
|
|
||||||
CloneClone = iota
|
|
||||||
)
|
|
||||||
|
|
||||||
type GitClonerPuller interface {
|
|
||||||
CloneOrPull(url string, pid int, defaultBranch string) (localRepoLoc string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type GitClientParam struct {
|
type GitClientParam struct {
|
||||||
CloneLocation string
|
CloneLocation string `yaml:"clone_location,omitempty"`
|
||||||
RemoteName string
|
Remote string `yaml:"remote,omitempty"`
|
||||||
RemoteURL *url.URL
|
OnClone string `yaml:"on_clone,omitempty"`
|
||||||
CloneMethod int
|
AutoPull bool `yaml:"auto_pull,omitempty"`
|
||||||
PullDepth int
|
Depth int `yaml:"depth,omitempty"`
|
||||||
AutoPull bool
|
QueueSize int `yaml:"queue_size,omitempty"`
|
||||||
|
QueueWorkerCount int `yaml:"worker_count,omitempty"`
|
||||||
QueueSize int
|
|
||||||
QueueWorkerCount int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type gitClient struct {
|
type gitClient struct {
|
||||||
GitClientParam
|
GitClientParam
|
||||||
|
|
||||||
|
hostnameProg *regexp.Regexp
|
||||||
|
|
||||||
queue taskq.Queue
|
queue taskq.Queue
|
||||||
cloneTask *taskq.Task
|
cloneTask *taskq.Task
|
||||||
pullTask *taskq.Task
|
pullTask *taskq.Task
|
||||||
|
@ -46,6 +40,8 @@ func NewClient(p GitClientParam) (*gitClient, error) {
|
||||||
c := &gitClient{
|
c := &gitClient{
|
||||||
GitClientParam: p,
|
GitClientParam: p,
|
||||||
|
|
||||||
|
hostnameProg: regexp.MustCompile(`([a-z0-1]+\.)+[a-z0-1]+`),
|
||||||
|
|
||||||
queue: queueFactory.RegisterQueue(&taskq.QueueOptions{
|
queue: queueFactory.RegisterQueue(&taskq.QueueOptions{
|
||||||
Name: "git-queue",
|
Name: "git-queue",
|
||||||
MaxNumWorker: int32(p.QueueWorkerCount),
|
MaxNumWorker: int32(p.QueueWorkerCount),
|
||||||
|
@ -68,21 +64,27 @@ func NewClient(p GitClientParam) (*gitClient, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *gitClient) getLocalRepoLoc(pid int) string {
|
func (c *gitClient) FetchLocalRepositoryPath(source fstree.RepositorySource) (localRepoLoc string, err error) {
|
||||||
return filepath.Join(c.CloneLocation, c.RemoteURL.Hostname(), strconv.Itoa(pid))
|
rid := source.GetRepositoryID()
|
||||||
|
cloneUrl := source.GetCloneURL()
|
||||||
|
defaultBranch := source.GetDefaultBranch()
|
||||||
|
|
||||||
|
// Parse the url
|
||||||
|
hostname := c.hostnameProg.FindString(cloneUrl)
|
||||||
|
if hostname == "" {
|
||||||
|
return "", fmt.Errorf("failed to match a valid hostname from \"%v\"", cloneUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *gitClient) CloneOrPull(url string, pid int, defaultBranch string) (localRepoLoc string, err error) {
|
localRepoLoc = filepath.Join(c.CloneLocation, hostname, strconv.Itoa(int(rid)))
|
||||||
localRepoLoc = c.getLocalRepoLoc(pid)
|
|
||||||
if _, err := os.Stat(localRepoLoc); os.IsNotExist(err) {
|
if _, err := os.Stat(localRepoLoc); os.IsNotExist(err) {
|
||||||
// Dispatch clone msg
|
// Dispatch clone msg
|
||||||
msg := c.cloneTask.WithArgs(context.Background(), url, defaultBranch, localRepoLoc)
|
msg := c.cloneTask.WithArgs(context.Background(), cloneUrl, defaultBranch, localRepoLoc)
|
||||||
msg.OnceInPeriod(time.Second, pid)
|
msg.OnceInPeriod(time.Second, rid)
|
||||||
c.queue.Add(msg)
|
c.queue.Add(msg)
|
||||||
} else if c.AutoPull {
|
} else if c.AutoPull {
|
||||||
// Dispatch pull msg
|
// Dispatch pull msg
|
||||||
msg := c.pullTask.WithArgs(context.Background(), localRepoLoc, defaultBranch)
|
msg := c.pullTask.WithArgs(context.Background(), localRepoLoc, defaultBranch)
|
||||||
msg.OnceInPeriod(time.Second, pid)
|
msg.OnceInPeriod(time.Second, rid)
|
||||||
c.queue.Add(msg)
|
c.queue.Add(msg)
|
||||||
}
|
}
|
||||||
return localRepoLoc, nil
|
return localRepoLoc, nil
|
||||||
|
|
10
git/clone.go
10
git/clone.go
|
@ -8,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *gitClient) clone(url string, defaultBranch string, dst string) error {
|
func (c *gitClient) clone(url string, defaultBranch string, dst string) error {
|
||||||
if c.CloneMethod == CloneInit {
|
if c.GitClientParam.OnClone == "init" {
|
||||||
// "Fake" cloning the repo by never actually talking to the git server
|
// "Fake" cloning the repo by never actually talking to the git server
|
||||||
// This skip a fetch operation that we would do if we where to do a proper clone
|
// This skip a fetch operation that we would do if we where to do a proper clone
|
||||||
// We can save a lot of time and network i/o doing it this way, at the cost of
|
// We can save a lot of time and network i/o doing it this way, at the cost of
|
||||||
|
@ -32,7 +32,7 @@ func (c *gitClient) clone(url string, defaultBranch string, dst string) error {
|
||||||
"git", "remote", "add",
|
"git", "remote", "add",
|
||||||
"-m", defaultBranch,
|
"-m", defaultBranch,
|
||||||
"--",
|
"--",
|
||||||
c.RemoteName, // name
|
c.GitClientParam.Remote, // name
|
||||||
url, // url
|
url, // url
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -45,7 +45,7 @@ func (c *gitClient) clone(url string, defaultBranch string, dst string) error {
|
||||||
"git", "config", "--local",
|
"git", "config", "--local",
|
||||||
"--",
|
"--",
|
||||||
fmt.Sprintf("branch.%s.remote", defaultBranch), // key
|
fmt.Sprintf("branch.%s.remote", defaultBranch), // key
|
||||||
c.RemoteName, // value
|
c.GitClientParam.Remote, // value
|
||||||
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,8 +66,8 @@ func (c *gitClient) clone(url string, defaultBranch string, dst string) error {
|
||||||
// Clone the repo
|
// Clone the repo
|
||||||
_, err := utils.ExecProcess(
|
_, err := utils.ExecProcess(
|
||||||
"git", "clone",
|
"git", "clone",
|
||||||
"--origin", c.RemoteName,
|
"--origin", c.GitClientParam.Remote,
|
||||||
"--depth", strconv.Itoa(c.PullDepth),
|
"--depth", strconv.Itoa(c.GitClientParam.Depth),
|
||||||
"--",
|
"--",
|
||||||
url, // repository
|
url, // repository
|
||||||
dst, // directory
|
dst, // directory
|
||||||
|
|
|
@ -23,9 +23,9 @@ func (c *gitClient) pull(repoPath string, defaultBranch string) error {
|
||||||
_, err = utils.ExecProcessInDir(
|
_, err = utils.ExecProcessInDir(
|
||||||
repoPath, // workdir
|
repoPath, // workdir
|
||||||
"git", "pull",
|
"git", "pull",
|
||||||
"--depth", strconv.Itoa(c.PullDepth),
|
"--depth", strconv.Itoa(c.GitClientParam.Depth),
|
||||||
"--",
|
"--",
|
||||||
c.RemoteName, // repository
|
c.GitClientParam.Remote, // repository
|
||||||
defaultBranch, // refspec
|
defaultBranch, // refspec
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
40
main.go
40
main.go
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -18,21 +17,12 @@ type (
|
||||||
Config struct {
|
Config struct {
|
||||||
FS FSConfig `yaml:"fs,omitempty"`
|
FS FSConfig `yaml:"fs,omitempty"`
|
||||||
Gitlab gitlab.GitlabClientConfig `yaml:"gitlab,omitempty"`
|
Gitlab gitlab.GitlabClientConfig `yaml:"gitlab,omitempty"`
|
||||||
Git GitConfig `yaml:"git,omitempty"`
|
Git git.GitClientParam `yaml:"git,omitempty"`
|
||||||
}
|
}
|
||||||
FSConfig struct {
|
FSConfig struct {
|
||||||
Mountpoint string `yaml:"mountpoint,omitempty"`
|
Mountpoint string `yaml:"mountpoint,omitempty"`
|
||||||
MountOptions string `yaml:"mountoptions,omitempty"`
|
MountOptions string `yaml:"mountoptions,omitempty"`
|
||||||
}
|
}
|
||||||
GitConfig struct {
|
|
||||||
CloneLocation string `yaml:"clone_location,omitempty"`
|
|
||||||
Remote string `yaml:"remote,omitempty"`
|
|
||||||
OnClone string `yaml:"on_clone,omitempty"`
|
|
||||||
AutoPull bool `yaml:"auto_pull,omitempty"`
|
|
||||||
Depth int `yaml:"depth,omitempty"`
|
|
||||||
QueueSize int `yaml:"queue_size,omitempty"`
|
|
||||||
QueueWorkerCount int `yaml:"worker_count,omitempty"`
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func loadConfig(configPath string) (*Config, error) {
|
func loadConfig(configPath string) (*Config, error) {
|
||||||
|
@ -56,7 +46,7 @@ func loadConfig(configPath string) (*Config, error) {
|
||||||
IncludeCurrentUser: true,
|
IncludeCurrentUser: true,
|
||||||
PullMethod: "http",
|
PullMethod: "http",
|
||||||
},
|
},
|
||||||
Git: GitConfig{
|
Git: git.GitClientParam{
|
||||||
CloneLocation: defaultCloneLocation,
|
CloneLocation: defaultCloneLocation,
|
||||||
Remote: "origin",
|
Remote: "origin",
|
||||||
OnClone: "init",
|
OnClone: "init",
|
||||||
|
@ -93,32 +83,12 @@ func makeGitlabConfig(config *Config) (*gitlab.GitlabClientConfig, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeGitConfig(config *Config) (*git.GitClientParam, error) {
|
func makeGitConfig(config *Config) (*git.GitClientParam, error) {
|
||||||
// Parse the gilab url
|
|
||||||
parsedGitlabURL, err := url.Parse(config.Gitlab.URL)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse on_clone
|
// parse on_clone
|
||||||
cloneMethod := 0
|
if config.Git.OnClone != "init" && config.Git.OnClone != "clone" {
|
||||||
if config.Git.OnClone == "init" {
|
|
||||||
cloneMethod = git.CloneInit
|
|
||||||
} else if config.Git.OnClone == "clone" {
|
|
||||||
cloneMethod = git.CloneClone
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("on_clone must be either \"init\" or \"clone\"")
|
return nil, fmt.Errorf("on_clone must be either \"init\" or \"clone\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &git.GitClientParam{
|
return &config.Git, nil
|
||||||
CloneLocation: config.Git.CloneLocation,
|
|
||||||
RemoteName: config.Git.Remote,
|
|
||||||
RemoteURL: parsedGitlabURL,
|
|
||||||
CloneMethod: cloneMethod,
|
|
||||||
AutoPull: config.Git.AutoPull,
|
|
||||||
PullDepth: config.Git.Depth,
|
|
||||||
QueueSize: config.Git.QueueSize,
|
|
||||||
QueueWorkerCount: config.Git.QueueWorkerCount,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -181,7 +151,7 @@ func main() {
|
||||||
err = fstree.Start(
|
err = fstree.Start(
|
||||||
mountpoint,
|
mountpoint,
|
||||||
parsedMountoptions,
|
parsedMountoptions,
|
||||||
&fstree.FSParam{GitImplementation: gitClient, GitPlatform: gitlabClient},
|
&fstree.FSParam{GitClient: gitClient, GitPlatform: gitlabClient},
|
||||||
*debug,
|
*debug,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue