2020-12-29 02:37:18 +00:00
|
|
|
package git
|
|
|
|
|
|
|
|
import (
|
2020-12-31 02:18:18 +00:00
|
|
|
"errors"
|
2020-12-29 02:37:18 +00:00
|
|
|
"net/url"
|
2020-12-31 02:18:18 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strconv"
|
2020-12-29 02:37:18 +00:00
|
|
|
)
|
|
|
|
|
2021-03-03 05:24:27 +00:00
|
|
|
const (
|
|
|
|
CloneInit = iota
|
|
|
|
CloneClone = iota
|
|
|
|
)
|
|
|
|
|
2020-12-31 02:18:18 +00:00
|
|
|
type GitClonerPuller interface {
|
|
|
|
CloneOrPull(url string, pid int, defaultBranch string) (localRepoLoc string, err error)
|
|
|
|
}
|
|
|
|
|
2020-12-29 02:37:18 +00:00
|
|
|
type GitClientParam struct {
|
2021-03-03 05:24:27 +00:00
|
|
|
CloneLocation string
|
|
|
|
RemoteName string
|
|
|
|
RemoteURL *url.URL
|
|
|
|
CloneMethod int
|
|
|
|
PullDepth int
|
|
|
|
AutoPull bool
|
2020-12-31 02:18:18 +00:00
|
|
|
|
|
|
|
CloneBuffSize int
|
|
|
|
CloneWorkerCount int
|
|
|
|
PullBuffSize int
|
|
|
|
PullWorkerCount int
|
2020-12-29 02:37:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type gitClient struct {
|
|
|
|
GitClientParam
|
2020-12-31 02:18:18 +00:00
|
|
|
cloneChan chan *gitCloneParam
|
|
|
|
pullChan chan *gitPullParam
|
2020-12-29 02:37:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewClient(p GitClientParam) (*gitClient, error) {
|
|
|
|
// Create the client
|
|
|
|
c := &gitClient{
|
|
|
|
GitClientParam: p,
|
2020-12-31 02:18:18 +00:00
|
|
|
cloneChan: make(chan *gitCloneParam, p.CloneBuffSize),
|
|
|
|
pullChan: make(chan *gitPullParam, p.PullBuffSize),
|
2020-12-29 02:37:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Start worker goroutines
|
2020-12-31 02:18:18 +00:00
|
|
|
for i := 0; i < p.CloneWorkerCount; i++ {
|
|
|
|
go c.cloneWorker()
|
|
|
|
}
|
|
|
|
for i := 0; i < p.PullWorkerCount; i++ {
|
|
|
|
go c.pullWorker()
|
2020-12-29 02:37:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return c, nil
|
|
|
|
}
|
2020-12-31 02:18:18 +00:00
|
|
|
|
|
|
|
func (c *gitClient) getLocalRepoLoc(pid int) string {
|
|
|
|
return filepath.Join(c.CloneLocation, c.RemoteURL.Hostname(), strconv.Itoa(pid))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *gitClient) CloneOrPull(url string, pid int, defaultBranch string) (localRepoLoc string, err error) {
|
|
|
|
localRepoLoc = c.getLocalRepoLoc(pid)
|
|
|
|
// TODO: Better manage concurrency, filter out duplicate requests
|
|
|
|
if _, err := os.Stat(localRepoLoc); os.IsNotExist(err) {
|
|
|
|
// Dispatch to clone worker
|
|
|
|
select {
|
|
|
|
case c.cloneChan <- &gitCloneParam{
|
|
|
|
url: url,
|
|
|
|
defaultBranch: defaultBranch,
|
|
|
|
dst: localRepoLoc,
|
|
|
|
}:
|
|
|
|
default:
|
|
|
|
return localRepoLoc, errors.New("failed to clone local repo")
|
|
|
|
}
|
|
|
|
} else if c.AutoPull {
|
|
|
|
// Dispatch to pull worker
|
|
|
|
select {
|
|
|
|
case c.pullChan <- &gitPullParam{
|
|
|
|
repoPath: localRepoLoc,
|
|
|
|
defaultBranch: defaultBranch,
|
|
|
|
}:
|
|
|
|
default:
|
|
|
|
return localRepoLoc, errors.New("failed to pull local repo")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return localRepoLoc, nil
|
|
|
|
}
|