go-git icon indicating copy to clipboard operation
go-git copied to clipboard

No support for ~username expansion in `PlainClone`

Open janakerman opened this issue 3 years ago • 1 comments

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
  • I've tested the above theory by exec'ing onto the git server and running git-upload-pack '~/cluster.git' works, but git-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.

janakerman avatar Dec 18 '21 23:12 janakerman

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!

github-actions[bot] avatar May 09 '24 07:05 github-actions[bot]