Initial commit

This commit is contained in:
2020-02-20 08:31:22 +01:00
commit b7bdd7bbea
17 changed files with 826 additions and 0 deletions

View File

@ -0,0 +1,12 @@
package project
import (
"net/url"
"gopkg.in/src-d/go-billy.v4"
)
type Fetcher interface {
Match(*url.URL) bool
Fetch(*url.URL) (billy.Filesystem, error)
}

98
internal/project/git.go Normal file
View File

@ -0,0 +1,98 @@
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{}
}

View File

@ -0,0 +1,51 @@
package project
import (
"net/url"
"testing"
)
func TestGitFetcher(t *testing.T) {
git := NewGitFetcher()
projectURL, err := url.Parse("forge.cadoles.com/wpetit/goweb")
if err != nil {
t.Fatal(err)
}
fs, err := git.Fetch(projectURL)
if err != nil {
t.Fatal(err)
}
if fs == nil {
t.Fatal("fs should not be nil")
}
}
func TestGitMatch(t *testing.T) {
testCases := []struct {
RawURL string
ShouldMatch bool
}{
{"git://wpetit/scaffold", true},
{"forge.cadoles.com/wpetit/scaffold", true},
}
git := NewGitFetcher()
for _, tc := range testCases {
func(rawURL string, shouldMatch bool) {
t.Run(rawURL, func(t *testing.T) {
projectURL, err := url.Parse(rawURL)
if err != nil {
t.Fatal(err)
}
if e, g := shouldMatch, git.Match(projectURL); g != e {
t.Errorf("git.Match(url): expected '%v', got '%v'", e, g)
}
})
}(tc.RawURL, tc.ShouldMatch)
}
}

33
internal/project/local.go Normal file
View File

@ -0,0 +1,33 @@
package project
import (
"net/url"
"strings"
"gopkg.in/src-d/go-billy.v4"
)
const LocalScheme = "local"
const FileScheme = "file"
type LocalFetcher struct{}
func (f *LocalFetcher) Fetch(url *url.URL) (billy.Filesystem, error) {
return nil, nil
}
func (f *LocalFetcher) Match(url *url.URL) bool {
if url.Scheme == LocalScheme || url.Scheme == FileScheme {
return true
}
return isFilesystemPath(url.Path)
}
func NewLocalFetcher() *LocalFetcher {
return &LocalFetcher{}
}
func isFilesystemPath(path string) bool {
return strings.HasPrefix(path, "./") || strings.HasPrefix(path, "/")
}

View File

@ -0,0 +1,33 @@
package project
import (
"net/url"
"testing"
)
func TestLocalMatch(t *testing.T) {
testCases := []struct {
RawURL string
ShouldMatch bool
}{
{"local://wpetit/scaffold", true},
{"./forge.cadoles.com/wpetit/scaffold", true},
}
local := NewLocalFetcher()
for _, tc := range testCases {
func(rawURL string, shouldMatch bool) {
t.Run(rawURL, func(t *testing.T) {
projectURL, err := url.Parse(rawURL)
if err != nil {
t.Fatal(err)
}
if e, g := shouldMatch, local.Match(projectURL); g != e {
t.Errorf("local.Match(url): expected '%v', got '%v'", e, g)
}
})
}(tc.RawURL, tc.ShouldMatch)
}
}