git-lfs/lfsapi/endpoint_finder_test.go
brian m. carlson f8de4cc7fe
Add support for local paths
Currently, we only support local remotes using file URLs, but not local
paths.  This is a highly requested feature, however, so implement
support for local paths as remotes.

First, fix the handling of local paths we already have: the handling of
absolute Unix-style paths.  Instead of checking for the remote to
contain a file URL to determine whether to append "info/lfs" to the URL,
look to see if the URL we're using is a file URL, which will catch local
paths which will have been rewritten as such by this point.  The
"info/lfs" part of the URL is not handled by the transfer adapter, so we
don't want to add it on.

If we get something that looks like it's not a URL, check if it's a
file on the file system, and if so, don't attempt to interpret it as an
SSH URL.  This fixes the confusion with Windows paths, which resemble
SSH-style locations with a single-letter alias as the host name.

Finally, when turning a local path into a file URL, turn the path into
an absolute one if possible and rewrite it using slashes, which is
required for file URLs.  Add several tests for the various cases: one
for Unix-style paths, one for native paths, and one for relative paths.
2019-11-14 17:23:12 +00:00

645 lines
20 KiB
Go

package lfsapi
import (
"runtime"
"testing"
"github.com/git-lfs/git-lfs/lfshttp"
"github.com/stretchr/testify/assert"
)
func TestEndpointDefaultsToOrigin(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.lfsurl": "abc",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "abc", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestEndpointOverridesOrigin(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.url": "abc",
"remote.origin.lfsurl": "def",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "abc", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestEndpointNoOverrideDefaultRemote(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.lfsurl": "abc",
"remote.other.lfsurl": "def",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "abc", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestEndpointUseAlternateRemote(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.lfsurl": "abc",
"remote.other.lfsurl": "def",
}))
e := finder.Endpoint("download", "other")
assert.Equal(t, "def", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "https://example.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestBareEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "https://example.com/foo/bar.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestEndpointSeparateClonePushUrl(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "https://example.com/foo/bar.git",
"remote.origin.pushurl": "https://readwrite.com/foo/bar.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
e = finder.Endpoint("upload", "")
assert.Equal(t, "https://readwrite.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestEndpointOverriddenSeparateClonePushLfsUrl(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "https://example.com/foo/bar.git",
"remote.origin.pushurl": "https://readwrite.com/foo/bar.git",
"remote.origin.lfsurl": "https://examplelfs.com/foo/bar",
"remote.origin.lfspushurl": "https://readwritelfs.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://examplelfs.com/foo/bar", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
e = finder.Endpoint("upload", "")
assert.Equal(t, "https://readwritelfs.com/foo/bar", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestEndpointGlobalSeparateLfsPush(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.url": "https://readonly.com/foo/bar",
"lfs.pushurl": "https://write.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://readonly.com/foo/bar", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
e = finder.Endpoint("upload", "")
assert.Equal(t, "https://write.com/foo/bar", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
}
func TestSSHEndpointOverridden(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "git@example.com:foo/bar",
"remote.origin.lfsurl": "lfs",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestSSHEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "ssh://git@example.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestSSHCustomPortEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "ssh://git@example.com:9000/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar", e.SshPath)
assert.Equal(t, "9000", e.SshPort)
}
func TestGitSSHEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "git+ssh://git@example.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestGitSSHCustomPortEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "git+ssh://git@example.com:9000/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar", e.SshPath)
assert.Equal(t, "9000", e.SshPort)
}
func TestSSHGitEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "ssh+git://git@example.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestSSHGitCustomPortEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "ssh+git://git@example.com:9000/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar", e.SshPath)
assert.Equal(t, "9000", e.SshPort)
}
func TestBareSSHEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "git@example.com:foo/bar.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar.git", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestBareSSSHEndpointWithCustomPortInBrackets(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "[git@example.com:2222]:foo/bar.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar.git", e.SshPath)
assert.Equal(t, "2222", e.SshPort)
}
func TestSSHEndpointFromGlobalLfsUrl(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.url": "git@example.com:foo/bar.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git", e.Url)
assert.Equal(t, "git@example.com", e.SshUserAndHost)
assert.Equal(t, "foo/bar.git", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestHTTPEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "http://example.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "http://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestBareHTTPEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "http://example.com/foo/bar.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "http://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestGitEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "git://example.com/foo/bar",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestGitEndpointAddsLfsSuffixWithCustomProtocol(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "git://example.com/foo/bar",
"lfs.gitprotocol": "http",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "http://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestBareGitEndpointAddsLfsSuffix(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "git://example.com/foo/bar.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
assert.Equal(t, "", e.SshUserAndHost)
assert.Equal(t, "", e.SshPath)
assert.Equal(t, "", e.SshPort)
}
func TestLocalPathEndpointAddsDotGitDir(t *testing.T) {
// Windows will add a drive letter to the paths below since we
// canonicalize them.
if runtime.GOOS == "windows" {
return
}
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "/local/path",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "file:///local/path/.git", e.Url)
}
func TestLocalPathEndpointPreservesDotGit(t *testing.T) {
// Windows will add a drive letter to the paths below since we
// canonicalize them.
if runtime.GOOS == "windows" {
return
}
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.origin.url": "/local/path.git",
}))
e := finder.Endpoint("download", "")
assert.Equal(t, "file:///local/path.git", e.Url)
}
func TestAccessConfig(t *testing.T) {
type accessTest struct {
AccessMode string
PrivateAccess bool
}
tests := map[string]accessTest{
"": {"none", false},
"basic": {"basic", true},
"BASIC": {"basic", true},
"private": {"basic", true},
"PRIVATE": {"basic", true},
"invalidauth": {"invalidauth", true},
}
for value, expected := range tests {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.url": "http://example.com",
"lfs.http://example.com.access": value,
"lfs.https://example.com.access": "bad",
}))
dl := finder.Endpoint("upload", "")
ul := finder.Endpoint("download", "")
if access := finder.AccessFor(dl.Url); access.Mode() != AccessMode(expected.AccessMode) {
t.Errorf("Expected AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
}
if access := finder.AccessFor(ul.Url); access.Mode() != AccessMode(expected.AccessMode) {
t.Errorf("Expected AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
}
}
// Test again but with separate push url
for value, expected := range tests {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.url": "http://example.com",
"lfs.pushurl": "http://examplepush.com",
"lfs.http://example.com.access": value,
"lfs.http://examplepush.com.access": value,
"lfs.https://example.com.access": "bad",
}))
dl := finder.Endpoint("upload", "")
ul := finder.Endpoint("download", "")
if access := finder.AccessFor(dl.Url); access.Mode() != AccessMode(expected.AccessMode) {
t.Errorf("Expected AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
}
if access := finder.AccessFor(ul.Url); access.Mode() != AccessMode(expected.AccessMode) {
t.Errorf("Expected AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
}
}
}
func TestAccessAbsentConfig(t *testing.T) {
finder := NewEndpointFinder(nil)
downloadAccess := finder.AccessFor(finder.Endpoint("download", "").Url)
assert.Equal(t, NoneAccess, downloadAccess.Mode())
uploadAccess := finder.AccessFor(finder.Endpoint("upload", "").Url)
assert.Equal(t, NoneAccess, uploadAccess.Mode())
}
func TestSetAccess(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{}))
url := "http://example.com"
access := finder.AccessFor(url)
assert.Equal(t, NoneAccess, access.Mode())
assert.Equal(t, url, access.url)
finder.SetAccess(access.Upgrade(NTLMAccess))
newAccess := finder.AccessFor(url)
assert.Equal(t, NTLMAccess, newAccess.Mode())
assert.Equal(t, url, newAccess.url)
}
func TestChangeAccess(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.http://example.com.access": "basic",
}))
url := "http://example.com"
access := finder.AccessFor(url)
assert.Equal(t, BasicAccess, access.Mode())
assert.Equal(t, url, access.url)
finder.SetAccess(access.Upgrade(NTLMAccess))
newAccess := finder.AccessFor(url)
assert.Equal(t, NTLMAccess, newAccess.Mode())
assert.Equal(t, url, newAccess.url)
}
func TestDeleteAccessWithNone(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.http://example.com.access": "basic",
}))
url := "http://example.com"
access := finder.AccessFor(url)
assert.Equal(t, BasicAccess, access.Mode())
assert.Equal(t, url, access.url)
finder.SetAccess(access.Upgrade(NoneAccess))
newAccess := finder.AccessFor(url)
assert.Equal(t, NoneAccess, newAccess.Mode())
assert.Equal(t, url, newAccess.url)
}
func TestDeleteAccessWithEmptyString(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"lfs.http://example.com.access": "basic",
}))
url := "http://example.com"
access := finder.AccessFor(url)
assert.Equal(t, BasicAccess, access.Mode())
assert.Equal(t, url, access.url)
finder.SetAccess(access.Upgrade(AccessMode("")))
newAccess := finder.AccessFor(url)
assert.Equal(t, NoneAccess, newAccess.Mode())
assert.Equal(t, url, newAccess.url)
}
type EndpointParsingTestCase struct {
Given string
Expected lfshttp.Endpoint
}
func (c *EndpointParsingTestCase) Assert(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"url.https://github.com/.insteadof": "gh:",
}))
actual := finder.NewEndpoint("upload", c.Given)
assert.Equal(t, c.Expected, actual, "lfsapi: expected endpoint for %q to be %#v (was %#v)", c.Given, c.Expected, actual)
}
func TestEndpointParsing(t *testing.T) {
// Note that many of these tests will produce silly or completely broken
// values for the Url, and that's okay: they work nevertheless.
for desc, c := range map[string]EndpointParsingTestCase{
"simple bare ssh": {
"git@github.com:git-lfs/git-lfs.git",
lfshttp.Endpoint{
Url: "https://github.com/git-lfs/git-lfs.git",
SshUserAndHost: "git@github.com",
SshPath: "git-lfs/git-lfs.git",
SshPort: "",
Operation: "",
},
},
"port bare ssh": {
"[git@ssh.github.com:443]:git-lfs/git-lfs.git",
lfshttp.Endpoint{
Url: "https://ssh.github.com/git-lfs/git-lfs.git",
SshUserAndHost: "git@ssh.github.com",
SshPath: "git-lfs/git-lfs.git",
SshPort: "443",
Operation: "",
},
},
"no user bare ssh": {
"github.com:git-lfs/git-lfs.git",
lfshttp.Endpoint{
Url: "https://github.com/git-lfs/git-lfs.git",
SshUserAndHost: "github.com",
SshPath: "git-lfs/git-lfs.git",
SshPort: "",
Operation: "",
},
},
"bare word bare ssh": {
"github:git-lfs/git-lfs.git",
lfshttp.Endpoint{
Url: "https://github/git-lfs/git-lfs.git",
SshUserAndHost: "github",
SshPath: "git-lfs/git-lfs.git",
SshPort: "",
Operation: "",
},
},
"insteadof alias": {
"gh:git-lfs/git-lfs.git",
lfshttp.Endpoint{
Url: "https://github.com/git-lfs/git-lfs.git",
SshUserAndHost: "",
SshPath: "",
SshPort: "",
Operation: "",
},
},
"remote helper": {
"remote::git-lfs/git-lfs.git",
lfshttp.Endpoint{
Url: "remote::git-lfs/git-lfs.git",
SshUserAndHost: "",
SshPath: "",
SshPort: "",
Operation: "",
},
},
} {
t.Run(desc, c.Assert)
}
}
type InsteadOfTestCase struct {
Given string
Operation string
Expected lfshttp.Endpoint
}
func (c *InsteadOfTestCase) Assert(t *testing.T) {
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
"remote.test.url": c.Given,
"url.https://example.com/.insteadof": "ex:",
"url.ssh://example.com/.pushinsteadof": "ex:",
"url.ssh://example.com/.insteadof": "exp:",
}))
actual := finder.Endpoint(c.Operation, "test")
assert.Equal(t, c.Expected, actual, "lfsapi: expected endpoint for %q to be %#v (was %#v)", c.Given, c.Expected, actual)
}
func TestInsteadOf(t *testing.T) {
// Note that many of these tests will produce silly or completely broken
// values for the Url, and that's okay: they work nevertheless.
for desc, c := range map[string]InsteadOfTestCase{
"insteadof alias (download)": {
"ex:git-lfs/git-lfs.git",
"download",
lfshttp.Endpoint{
Url: "https://example.com/git-lfs/git-lfs.git/info/lfs",
SshUserAndHost: "",
SshPath: "",
SshPort: "",
Operation: "download",
},
},
"pushinsteadof alias (upload)": {
"ex:git-lfs/git-lfs.git",
"upload",
lfshttp.Endpoint{
Url: "https://example.com/git-lfs/git-lfs.git/info/lfs",
SshUserAndHost: "example.com",
SshPath: "git-lfs/git-lfs.git",
SshPort: "",
Operation: "upload",
},
},
"exp alias (download)": {
"exp:git-lfs/git-lfs.git",
"download",
lfshttp.Endpoint{
Url: "https://example.com/git-lfs/git-lfs.git/info/lfs",
SshUserAndHost: "example.com",
SshPath: "git-lfs/git-lfs.git",
SshPort: "",
Operation: "download",
},
},
"exp alias (upload)": {
"exp:git-lfs/git-lfs.git",
"upload",
lfshttp.Endpoint{
Url: "https://example.com/git-lfs/git-lfs.git/info/lfs",
SshUserAndHost: "example.com",
SshPath: "git-lfs/git-lfs.git",
SshPort: "",
Operation: "upload",
},
},
} {
t.Run(desc, c.Assert)
}
}
func TestNewEndpointFromCloneURLWithConfig(t *testing.T) {
expected := "https://foo/bar.git/info/lfs"
tests := []string{
"https://foo/bar",
"https://foo/bar/",
"https://foo/bar.git",
"https://foo/bar.git/",
}
finder := NewEndpointFinder(nil)
for _, actual := range tests {
e := finder.NewEndpointFromCloneURL("upload", actual)
if e.Url != expected {
t.Errorf("%s returned bad endpoint url %s", actual, e.Url)
}
}
}