Skip to content

Improved SSH support: non-bare urls, custom ports, and GIT_SSH/plink#404

Merged
technoweenie merged 2 commits intogit-lfs:masterfrom
sinbad:ssh_urls
Jul 6, 2015
Merged

Improved SSH support: non-bare urls, custom ports, and GIT_SSH/plink#404
technoweenie merged 2 commits intogit-lfs:masterfrom
sinbad:ssh_urls

Conversation

@sinbad
Copy link
Contributor

@sinbad sinbad commented Jun 17, 2015

  • Full SSH urls e.g. ssh://user@host/repo
  • Custom ports in both bare and full urls
  • GIT_SSH environment for alternate ssh clients
  • Explicit support for plink.exe and TortoisePlink.exe

Depends on #403 (included in PR)

@technoweenie
Copy link
Contributor

Can you merge the latest master now that #403 has been merged? Rebase if you like.

lfs/config.go Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of this giant method. I'd prefer to have something that calls internal functions:

endpoint := Endpoint{Url: urlstr}
u, err := url.Parse(urlstr)
if err != nil {
  // right now just {user}@{host}:{path}, but maybe others one day?
  processSshRemote(urlstr)
}

switch u.Scheme {
case "http", "https": processHttpUrl(u)
case "ssh": processSshUrl(u)
default: endpoint.Url = ENDPOINT_URL_UNKNOWN
}

Note: feel free to override my suggestions on method or variable names.

Minor nitpick: I tend to use rawurl. I don't like having type related suffixes on variable names. Maybe it's from my experience using hungarian notation in VB/Access code :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - rebased and will refactor a little in next commit.

You did VB/Access too eh? We should commiserate over a beer one day ;)

lfs/config.go Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer early returns.

if u.Scheme != "" || u.Path == "" {
    return u
}

// This might be a bare SSH URL
// Turn it into ssh:// for simplicity of extraction later
parts := strings.Split(u.Path, ":")
if len(parts) < 2 {
    return u
}

// Treat presence of ':' as a bare URL
var newPath string
if len(parts) > 2 { // port included; really should only ever be 3 parts
    newPath = fmt.Sprintf("%v:%v", parts[0], strings.Join(parts[1:], "/"))
} else {
    newPath = strings.Join(parts, "/")
}

newrawurl := fmt.Sprintf("ssh://%v", newPath)
newu, err := url.Parse(newrawurl)
if err != nil {
    return u
}

return newu

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another possibility is a switch statement:

var newPath string
switch {
case len(parts) < 2:
    return u
case len(parts) == 2:
    newPath = strings.Join(parts, "/")
default:
    // port included; really should only ever be 3 parts
    newPath = fmt.Sprintf("%v:%v", parts[0], strings.Join(parts[1:], "/"))
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely prefer early returns vs multiple levels of nesting. 👍

@bozaro
Copy link
Contributor

bozaro commented Jun 19, 2015

Without this change, you can not use SSH-connections multiplexing on Windows.
I think this latest update, which can give a appreciable performance boost without using batch api.
It would be nice if it was included in v0.5.2 (#281).

@technoweenie
Copy link
Contributor

This PR doesn't look ready, so it likely won't make it in. We can release v0.5.3 whenever we want though.

@sinbad
Copy link
Contributor Author

sinbad commented Jun 19, 2015

AFAIK the only thing that's "not ready" about it is stylistic preferences?

@technoweenie
Copy link
Contributor

Yes, and a merge conflict with master.

@sinbad
Copy link
Contributor Author

sinbad commented Jun 19, 2015

OK, that must be new in the last day or two. Will come back to this next week.

@rubyist
Copy link
Contributor

rubyist commented Jun 19, 2015

Are we doing ssh multiplexing in this PR? If so, has it been benchmarked with large numbers of large files? It is my understanding that ssh multiplexing starts to fall over when connections with large amounts of data are involved, though I am admittedly unfamiliar with plink.

@technoweenie
Copy link
Contributor

There's also another patch I'm holding back because of insufficient testing. We can roll v0.5.3 when these two are ready. I'm anxious to get v0.5.2 out because it's been way too long since the last release.

@rubyist: We may be able to punt on that concern for now until we're reviewing the SSH API.

@sinbad
Copy link
Contributor Author

sinbad commented Jun 19, 2015

Are we doing ssh multiplexing in this PR? If so, has it been benchmarked

All this PR does is support ssh:// url forms, custom ports, and the GIT_SSH env var. Its performance characteristics are identical to master since the ssh calls themselves happen exactly the same way, all it does is support cases that would previously fail.

My other PR on full SSH support opens only Config.ConcurrentTransfers() SSH connections to run the API over and pipes everything through those.

@rubyist
Copy link
Contributor

rubyist commented Jun 19, 2015

@sinbad 👍 that sounds OK then. My concerns were around using something like ssh's ControlMaster (or equivalents in plink, etc), using ConcurrentTransfers() connections with the transfer queue should be just fine.

@sinbad
Copy link
Contributor Author

sinbad commented Jun 19, 2015

My concerns were around using something like ssh's ControlMaster (or equivalents in plink, etc), using ConcurrentTransfers() connections with the transfer queue should be just fine.

Yeah I did consider adding another config parameter that could override ConcurrentTransfers() for SSH connections, using a default lower limit but for simplicity I didn't, and the default 3 should be OK for all but the most totalitarian server admin.

@technoweenie technoweenie mentioned this pull request Jun 19, 2015
38 tasks
@bozaro
Copy link
Contributor

bozaro commented Jun 19, 2015

Are we doing ssh multiplexing in this PR? If so, has it been benchmarked

I make little benchmark on Windows/Linux with our project repository #376 (4231 LFS files, working copy size: 3.6G, original repository size: ~50G). Local gigabit network environment.

On Linux:
I create simple config ~/.ssh/config:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlPersist 10m

This changes enable using single SSH connection for all git-lfs-authenticate requests.
Clone time reduced from 1436 sec to 541 sec (2.65X faster, ~0.216 sec per file).

On Windows:
I try to use similar configurations with differ OpenSSH versions. It looks that OpenSSH this feature is not supported on Windows.

A similar function is in Putty (plink.exe), but its use needs support GIT_SSH environment variable (this PR).

The effect of multiplex under Windows, I did not measure.

This was referenced Jun 19, 2015
* Full SSH urls e.g. ssh://user@host/repo
* Custom ports in both bare and full urls
* GIT_SSH environment for alternate ssh clients
* Explicit support for plink.exe and TortoisePlink.exe
@sinbad
Copy link
Contributor Author

sinbad commented Jun 22, 2015

Rebased on master & added early-outs, should be ready for inclusion in 0.5.3 now.

lfs/endpoint.go Outdated
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we really return an empty Endpoint in case of err != nil? Why not Endpoint{Url: rawurl}?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty much anything will go through the default: route, but for consistency with the other routes I've returned EndpointUrlUnknown in that case. You have to throw something pretty whacky at url.Parse for it to return an error (none of the tests with bare strings manage it).

@technoweenie technoweenie merged commit 2892978 into git-lfs:master Jul 6, 2015
technoweenie added a commit that referenced this pull request Jul 6, 2015
technoweenie added a commit that referenced this pull request Jul 7, 2015
technoweenie added a commit that referenced this pull request Jul 22, 2015
technoweenie added a commit that referenced this pull request Jul 22, 2015
technoweenie added a commit that referenced this pull request Jul 22, 2015
Backport #404 for v0.5.x: Improved SSH support: non-bare urls, custom ports, and GIT_SSH/plink
@sinbad sinbad deleted the ssh_urls branch August 6, 2015 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants