go-git
go-git copied to clipboard
No support for ~username expansion in `PlainClone`
Context
The git clone docs state that ~ expansion is valid in a clone URL:
The ssh and git protocols additionally support ~username expansion:
- ssh://[user@]host.xz[:port]/~[user]/path/to/repo.git/
- git://host.xz[:port]/~[user]/path/to/repo.git/
- [user@]host.xz:/~[user]/path/to/repo.git/
Observed
A PlainClone
with the following repository URL ssh://git@localhost/~/cluster.git
results in the error repository not found
, even though git clone ssh://git@localhost/~/cluster.git
is successful.
A PlainClone
with the full path to the repo works as expected ssh://git@localhost/home/git/cluster.git
. (Well, fails with reference not found
but I'm sure that's something else.)
I believe this is because the following command is executed over SSH "git-upload-pack '/~/cluster.git'"
when it should not have a leading /
.
Details
- I'm running a local git server using Docker
sudo docker run -p 22:22 -v /tmp/keys:/git-server/keys -v /tmp/repos:/git-server/repos -e REPO=cluster.git -e TAR_URL="https://github.com/stefanprodan/podinfo/archive/3.2.0.tar.gz" fluxcd/gitsrv:latest
- The container's
git
user's home dir is/home/git/
- The repository I'm attempting to close is at
/home/git/cluster.git
- The container's
- I've tested the above theory by exec'ing onto the git server and running
git-upload-pack '~/cluster.git'
works, butgit-upload-pack '/~/cluster.git'
does not (note leading/
in the path in the latter).
This is reproducible with something like this:
auth, err := ssh.NewPublicKeysFromFile("git", "/tmp/keys/id_rsa", "")
if err != nil {
panic(err)
}
_, err = gogit.PlainCloneContext(context.Background(), "/tmp/test", false, &gogit.CloneOptions{
URL: "ssh://git@localhost/~/cluster.git",
Auth: auth,
RemoteName: gogit.DefaultRemoteName,
ReferenceName: "master",
SingleBranch: true,
NoCheckout: false,
Progress: nil,
Tags: gogit.NoTags,
})
if err != nil {
panic(err)
}
Potential solutions
I've pondered on adding some logic to plumbing/transport/ssh/common.go:endpointToCommand
to detect when the first path segment is ~
and remove the leading /
. I'd like to write a test for this but I haven't figured out a nice way to do that yet without polluting the current user's home directory.
To help us keep things tidy and focus on the active tasks, we've introduced a stale bot to spot issues/PRs that haven't had any activity in a while.
This particular issue hasn't had any updates or activity in the past 90 days, so it's been labeled as 'stale'. If it remains inactive for the next 30 days, it'll be automatically closed.
We understand everyone's busy, but if this issue is still important to you, please feel free to add a comment or make an update to keep it active.
Thanks for your understanding and cooperation!