scaffold/internal/project/git.go

108 lines
2.2 KiB
Go

package project
import (
"fmt"
"net/url"
"os"
"strings"
"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"
const HTTPScheme = "http"
const HTTPSScheme = "https"
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 = ""
}
fmt.Printf("Cloning repository '%s'.\n", url.String())
repo, err := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{
URL: url.String(),
Auth: auth,
ReferenceName: branchName,
Progress: os.Stdout,
})
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")
}
fmt.Printf("Checking out branch '%s'.\n", 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
}
if (url.Scheme == HTTPSScheme || url.Scheme == HTTPScheme) && strings.HasSuffix(url.Path, ".git") {
return true
}
isFilesystemPath := isFilesystemPath(url.Path)
if url.Scheme == "" && !isFilesystemPath {
return true
}
return false
}
func NewGitFetcher() *GitFetcher {
return &GitFetcher{}
}