package project import ( "log" "net/url" "github.com/pkg/errors" "gopkg.in/src-d/go-billy.v4" "gopkg.in/src-d/go-billy.v4/memfs" git "gopkg.in/src-d/go-git.v4" "gopkg.in/src-d/go-git.v4/plumbing" "gopkg.in/src-d/go-git.v4/plumbing/transport" "gopkg.in/src-d/go-git.v4/plumbing/transport/http" "gopkg.in/src-d/go-git.v4/storage/memory" ) const GitScheme = "git" type GitFetcher struct{} func (f *GitFetcher) Fetch(url *url.URL) (billy.Filesystem, error) { fs := memfs.New() var auth transport.AuthMethod if user := url.User; user != nil { user := url.User basicAuth := &http.BasicAuth{ Username: user.Username(), } password, exists := user.Password() if exists { basicAuth.Password = password } auth = basicAuth } if url.Scheme == "" { url.Scheme = "https" } branchName := plumbing.NewBranchReferenceName("master") if url.Fragment != "" { branchName = plumbing.NewBranchReferenceName(url.Fragment) url.Fragment = "" } log.Printf("Cloning repository '%s'...", url.String()) repo, err := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{ URL: url.String(), Auth: auth, ReferenceName: branchName, }) if err != nil { if err == transport.ErrRepositoryNotFound { return nil, errors.Wrapf(err, "could not find repository") } return nil, errors.Wrap(err, "could not clone repository") } worktree, err := repo.Worktree() if err != nil { return nil, errors.Wrap(err, "could not retrieve worktree") } log.Printf("Checking out branch '%s'...", branchName) err = worktree.Checkout(&git.CheckoutOptions{ Force: true, Branch: branchName, }) if err != nil { return nil, errors.Wrapf(err, "could not checkout branch '%s'", branchName) } return fs, nil } func (f *GitFetcher) Match(url *url.URL) bool { if url.Scheme == GitScheme { return true } isFilesystemPath := isFilesystemPath(url.Path) if url.Scheme == "" && !isFilesystemPath { return true } return false } func NewGitFetcher() *GitFetcher { return &GitFetcher{} }