2016-12-19 18:45:22 +00:00
|
|
|
package lfsapi
|
2016-12-14 04:08:05 +00:00
|
|
|
|
|
|
|
import (
|
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-13 21:16:45 +00:00
|
|
|
"runtime"
|
2016-12-14 04:08:05 +00:00
|
|
|
"testing"
|
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
"github.com/git-lfs/git-lfs/creds"
|
2018-09-06 21:42:41 +00:00
|
|
|
"github.com/git-lfs/git-lfs/lfshttp"
|
2016-12-14 04:08:05 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestEndpointDefaultsToOrigin(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.lfsurl": "abc",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
assert.Equal(t, "abc", e.Url)
|
|
|
|
assert.Equal(t, "", e.SshUserAndHost)
|
|
|
|
assert.Equal(t, "", e.SshPath)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEndpointOverridesOrigin(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"lfs.url": "abc",
|
|
|
|
"remote.origin.lfsurl": "def",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
assert.Equal(t, "abc", e.Url)
|
|
|
|
assert.Equal(t, "", e.SshUserAndHost)
|
|
|
|
assert.Equal(t, "", e.SshPath)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEndpointNoOverrideDefaultRemote(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.lfsurl": "abc",
|
|
|
|
"remote.other.lfsurl": "def",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
assert.Equal(t, "abc", e.Url)
|
|
|
|
assert.Equal(t, "", e.SshUserAndHost)
|
|
|
|
assert.Equal(t, "", e.SshPath)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEndpointUseAlternateRemote(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.lfsurl": "abc",
|
|
|
|
"remote.other.lfsurl": "def",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "other")
|
2016-12-14 04:08:05 +00:00
|
|
|
assert.Equal(t, "def", e.Url)
|
|
|
|
assert.Equal(t, "", e.SshUserAndHost)
|
|
|
|
assert.Equal(t, "", e.SshPath)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestEndpointAddsLfsSuffix(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "https://example.com/foo/bar",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "https://example.com/foo/bar.git",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "https://example.com/foo/bar.git",
|
|
|
|
"remote.origin.pushurl": "https://readwrite.com/foo/bar.git",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
assert.Equal(t, "https://example.com/foo/bar.git/info/lfs", e.Url)
|
|
|
|
assert.Equal(t, "", e.SshUserAndHost)
|
|
|
|
assert.Equal(t, "", e.SshPath)
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e = finder.Endpoint("upload", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"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",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
assert.Equal(t, "https://examplelfs.com/foo/bar", e.Url)
|
|
|
|
assert.Equal(t, "", e.SshUserAndHost)
|
|
|
|
assert.Equal(t, "", e.SshPath)
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e = finder.Endpoint("upload", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"lfs.url": "https://readonly.com/foo/bar",
|
|
|
|
"lfs.pushurl": "https://write.com/foo/bar",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
assert.Equal(t, "https://readonly.com/foo/bar", e.Url)
|
|
|
|
assert.Equal(t, "", e.SshUserAndHost)
|
|
|
|
assert.Equal(t, "", e.SshPath)
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e = finder.Endpoint("upload", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "git@example.com:foo/bar",
|
|
|
|
"remote.origin.lfsurl": "lfs",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "ssh://git@example.com/foo/bar",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "ssh://git@example.com:9000/foo/bar",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2019-07-15 21:05:09 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2016-12-14 04:08:05 +00:00
|
|
|
func TestBareSSHEndpointAddsLfsSuffix(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "git@example.com:foo/bar.git",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2018-09-05 11:41:16 +00:00
|
|
|
func TestBareSSSHEndpointWithCustomPortInBrackets(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2018-09-05 11:41:16 +00:00
|
|
|
"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)
|
|
|
|
}
|
|
|
|
|
2016-12-14 04:08:05 +00:00
|
|
|
func TestSSHEndpointFromGlobalLfsUrl(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"lfs.url": "git@example.com:foo/bar.git",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "http://example.com/foo/bar",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "http://example.com/foo/bar.git",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "git://example.com/foo/bar",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "git://example.com/foo/bar",
|
|
|
|
"lfs.gitprotocol": "http",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-14 04:08:05 +00:00
|
|
|
"remote.origin.url": "git://example.com/foo/bar.git",
|
|
|
|
}))
|
|
|
|
|
2016-12-19 18:45:22 +00:00
|
|
|
e := finder.Endpoint("download", "")
|
2016-12-14 04:08:05 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2018-03-10 14:43:44 +00:00
|
|
|
func TestLocalPathEndpointAddsDotGitDir(t *testing.T) {
|
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-13 21:16:45 +00:00
|
|
|
// Windows will add a drive letter to the paths below since we
|
|
|
|
// canonicalize them.
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2018-03-10 14:43:44 +00:00
|
|
|
"remote.origin.url": "/local/path",
|
|
|
|
}))
|
|
|
|
e := finder.Endpoint("download", "")
|
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-13 21:16:45 +00:00
|
|
|
assert.Equal(t, "file:///local/path/.git", e.Url)
|
2018-03-10 14:43:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestLocalPathEndpointPreservesDotGit(t *testing.T) {
|
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-13 21:16:45 +00:00
|
|
|
// Windows will add a drive letter to the paths below since we
|
|
|
|
// canonicalize them.
|
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2018-03-10 14:43:44 +00:00
|
|
|
"remote.origin.url": "/local/path.git",
|
|
|
|
}))
|
|
|
|
e := finder.Endpoint("download", "")
|
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-13 21:16:45 +00:00
|
|
|
assert.Equal(t, "file:///local/path.git", e.Url)
|
2018-03-10 14:43:44 +00:00
|
|
|
}
|
|
|
|
|
2016-12-19 18:55:47 +00:00
|
|
|
func TestAccessConfig(t *testing.T) {
|
|
|
|
type accessTest struct {
|
2018-09-20 17:21:42 +00:00
|
|
|
AccessMode string
|
2016-12-19 18:55:47 +00:00
|
|
|
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 {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-19 18:55:47 +00:00
|
|
|
"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", "")
|
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
if access := finder.AccessFor(dl.Url); access.Mode() != creds.AccessMode(expected.AccessMode) {
|
|
|
|
t.Errorf("Expected creds.AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
|
2016-12-19 18:55:47 +00:00
|
|
|
}
|
2019-11-28 19:03:52 +00:00
|
|
|
if access := finder.AccessFor(ul.Url); access.Mode() != creds.AccessMode(expected.AccessMode) {
|
|
|
|
t.Errorf("Expected creds.AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
|
2016-12-19 18:55:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Test again but with separate push url
|
|
|
|
for value, expected := range tests {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-19 18:55:47 +00:00
|
|
|
"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", "")
|
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
if access := finder.AccessFor(dl.Url); access.Mode() != creds.AccessMode(expected.AccessMode) {
|
|
|
|
t.Errorf("Expected creds.AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
|
2016-12-19 18:55:47 +00:00
|
|
|
}
|
2019-11-28 19:03:52 +00:00
|
|
|
if access := finder.AccessFor(ul.Url); access.Mode() != creds.AccessMode(expected.AccessMode) {
|
|
|
|
t.Errorf("Expected creds.AccessMode() with value %q to be %v, got %v", value, expected.AccessMode, access)
|
2016-12-19 18:55:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAccessAbsentConfig(t *testing.T) {
|
|
|
|
finder := NewEndpointFinder(nil)
|
2018-10-02 23:35:54 +00:00
|
|
|
|
|
|
|
downloadAccess := finder.AccessFor(finder.Endpoint("download", "").Url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.NoneAccess, downloadAccess.Mode())
|
2018-10-02 23:35:54 +00:00
|
|
|
|
|
|
|
uploadAccess := finder.AccessFor(finder.Endpoint("upload", "").Url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.NoneAccess, uploadAccess.Mode())
|
2016-12-19 18:55:47 +00:00
|
|
|
}
|
|
|
|
|
2016-12-19 19:24:22 +00:00
|
|
|
func TestSetAccess(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{}))
|
2018-09-24 18:50:09 +00:00
|
|
|
url := "http://example.com"
|
|
|
|
access := finder.AccessFor(url)
|
2016-12-19 19:24:22 +00:00
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.NoneAccess, access.Mode())
|
|
|
|
assert.Equal(t, url, access.URL())
|
2018-09-24 18:50:09 +00:00
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
finder.SetAccess(access.Upgrade(creds.NTLMAccess))
|
2018-09-24 18:50:09 +00:00
|
|
|
|
|
|
|
newAccess := finder.AccessFor(url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.NTLMAccess, newAccess.Mode())
|
|
|
|
assert.Equal(t, url, newAccess.URL())
|
2016-12-19 19:24:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestChangeAccess(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-19 19:24:22 +00:00
|
|
|
"lfs.http://example.com.access": "basic",
|
|
|
|
}))
|
|
|
|
|
2018-09-24 18:50:09 +00:00
|
|
|
url := "http://example.com"
|
|
|
|
access := finder.AccessFor(url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.BasicAccess, access.Mode())
|
|
|
|
assert.Equal(t, url, access.URL())
|
2018-09-24 18:50:09 +00:00
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
finder.SetAccess(access.Upgrade(creds.NTLMAccess))
|
2018-09-24 18:50:09 +00:00
|
|
|
|
|
|
|
newAccess := finder.AccessFor(url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.NTLMAccess, newAccess.Mode())
|
|
|
|
assert.Equal(t, url, newAccess.URL())
|
2016-12-19 19:24:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteAccessWithNone(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-19 19:24:22 +00:00
|
|
|
"lfs.http://example.com.access": "basic",
|
|
|
|
}))
|
|
|
|
|
2018-09-24 18:50:09 +00:00
|
|
|
url := "http://example.com"
|
|
|
|
|
|
|
|
access := finder.AccessFor(url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.BasicAccess, access.Mode())
|
|
|
|
assert.Equal(t, url, access.URL())
|
2018-09-24 18:50:09 +00:00
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
finder.SetAccess(access.Upgrade(creds.NoneAccess))
|
2018-09-24 18:50:09 +00:00
|
|
|
|
|
|
|
newAccess := finder.AccessFor(url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.NoneAccess, newAccess.Mode())
|
|
|
|
assert.Equal(t, url, newAccess.URL())
|
2016-12-19 19:24:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeleteAccessWithEmptyString(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
2016-12-19 19:24:22 +00:00
|
|
|
"lfs.http://example.com.access": "basic",
|
|
|
|
}))
|
|
|
|
|
2018-09-24 18:50:09 +00:00
|
|
|
url := "http://example.com"
|
|
|
|
|
|
|
|
access := finder.AccessFor(url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.BasicAccess, access.Mode())
|
|
|
|
assert.Equal(t, url, access.URL())
|
2018-09-24 18:50:09 +00:00
|
|
|
|
2019-11-28 19:03:52 +00:00
|
|
|
finder.SetAccess(access.Upgrade(creds.AccessMode("")))
|
2018-09-24 18:50:09 +00:00
|
|
|
|
|
|
|
newAccess := finder.AccessFor(url)
|
2019-11-28 19:03:52 +00:00
|
|
|
assert.Equal(t, creds.NoneAccess, newAccess.Mode())
|
|
|
|
assert.Equal(t, url, newAccess.URL())
|
2016-12-19 19:24:22 +00:00
|
|
|
}
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
|
|
|
|
type EndpointParsingTestCase struct {
|
|
|
|
Given string
|
2018-09-06 21:42:41 +00:00
|
|
|
Expected lfshttp.Endpoint
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *EndpointParsingTestCase) Assert(t *testing.T) {
|
2018-09-06 21:42:41 +00:00
|
|
|
finder := NewEndpointFinder(lfshttp.NewContext(nil, nil, map[string]string{
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
"url.https://github.com/.insteadof": "gh:",
|
|
|
|
}))
|
2018-10-26 17:41:07 +00:00
|
|
|
actual := finder.NewEndpoint("upload", c.Given)
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
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",
|
2018-09-06 21:42:41 +00:00
|
|
|
lfshttp.Endpoint{
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
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",
|
2018-09-06 21:42:41 +00:00
|
|
|
lfshttp.Endpoint{
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
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",
|
2018-09-06 21:42:41 +00:00
|
|
|
lfshttp.Endpoint{
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
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",
|
2018-09-06 21:42:41 +00:00
|
|
|
lfshttp.Endpoint{
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
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",
|
2018-09-06 21:42:41 +00:00
|
|
|
lfshttp.Endpoint{
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
Url: "https://github.com/git-lfs/git-lfs.git",
|
|
|
|
SshUserAndHost: "",
|
|
|
|
SshPath: "",
|
|
|
|
SshPort: "",
|
|
|
|
Operation: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"remote helper": {
|
|
|
|
"remote::git-lfs/git-lfs.git",
|
2018-09-06 21:42:41 +00:00
|
|
|
lfshttp.Endpoint{
|
lfsapi: handle SSH hostnames and aliases without users
It's very common for a user to specify an SSH remote that refers to an
alias in their gitconfig file. For example, if a user must use
different SSH keys when pushing to different remotes, setting different
aliases that use those different keys is the simplest and easiest way to
accomplish that goal.
Unfortunately, our parsing logic was broken for SSH remotes that used
bare SSH URLs (that is, without “ssh://”) with a hostname or alias, but
without a username component. The URL parser we used saw the hostname
portion as the scheme of a URL, and we passed through any URLs with
unknown schemes. This led to a failure to push, since we misparsed the
URL as a non-SSH URL and gave up when it also didn't look like an
HTTP(S) URL.
If we get an unknown “scheme” when parsing a URL, check if the URL uses
a remote helper (that is, it contains a double colon), and pass it
through. Otherwise, do what Git does, and assume the URL is in fact an
SSH URL, and handle it accordingly.
We already handle the url.insteadof syntax properly, even if it looks
like a scheme. Add tests that we continue to do so, and for the new
code and all the various permutations mentioned above, and update the
existing integration test to reflect our new parsing strategy.
2018-09-05 21:23:12 +00:00
|
|
|
Url: "remote::git-lfs/git-lfs.git",
|
|
|
|
SshUserAndHost: "",
|
|
|
|
SshPath: "",
|
|
|
|
SshPort: "",
|
|
|
|
Operation: "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
t.Run(desc, c.Assert)
|
|
|
|
}
|
|
|
|
}
|
2018-09-06 21:42:41 +00:00
|
|
|
|
2018-10-26 19:16:07 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:42:41 +00:00
|
|
|
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 {
|
2018-10-26 17:41:07 +00:00
|
|
|
e := finder.NewEndpointFromCloneURL("upload", actual)
|
2018-09-06 21:42:41 +00:00
|
|
|
if e.Url != expected {
|
|
|
|
t.Errorf("%s returned bad endpoint url %s", actual, e.Url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|