git-lfs/lfsapi/endpoint_finder_test.go
brian m. carlson f3b0fc88c1
lfsapi: support pushInsteadOf aliases
For pushes, Git looks at both the insteadOf and pushInsteadOf aliases,
and uses the latter in preference to the former.  Teach Git LFS to honor
pushInsteadOf as well when uploading.
2018-10-31 15:10:54 +00:00

584 lines
18 KiB
Go

package lfsapi
import (
"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 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) {
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/info/lfs", e.Url)
}
func TestLocalPathEndpointPreservesDotGit(t *testing.T) {
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/info/lfs", 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)
}
}
}