NeogitOrg / neogit

An interactive and powerful Git interface for Neovim, inspired by Magit
MIT License
3.86k stars 227 forks source link

Improve parsing of url's in all cases, but specifically for ssh cases. #1201

Closed theherk closed 6 months ago

theherk commented 6 months ago

In my case, in addition to the default git_services, I use a hosted Gitlab that uses some ssh tunneling to reach the destination using a port other than standard. Using the parsing as is results in parsing the owner as <port>/actual/owner. For example ssh://gitlab.priv:2222/priv/group/repo.git yields owner 2222/priv/group which constructs a bad url with configuration ["gitlab.priv"] = "https://gitlab.priv/${owner}/${repository}/-/merge_requests/new?merge_request[source_branch]=${branch_name}&merge_request[target_branch]=main".

This probably generally works, because most users of ssh remotes will either use the git scheme or the default port 22, without specifying.

This patch introduces a more robust git url parsing library function, with support for more url schemes. It also maintains compatibility with the existing implementation where owner is set to the entire path part which is not the repository name; which is correct in the basic gitlab / github cases, but not in many other git cases.

It has been tested with the following url's:

Test Results ```bash { host = "github.com", owner = "owner", proto = "git", repo = "repo", repository = "repo", url = "git@github.com:owner/repo.git", user = "git" } { host = "github.com", owner = "owner", path = "owner", proto = "https", repo = "repo", repository = "repo", url = "https://github.com/owner/repo.git" } { host = "gitlab.com", owner = "owner", proto = "git", repo = "repo", repository = "repo", url = "git@gitlab.com:owner/repo.git", user = "git" } { host = "gitlab.com", owner = "owner", path = "owner", proto = "https", repo = "repo", repository = "repo", url = "https://gitlab.com/owner/repo.git" } { host = "gitlab.priv", owner = "project/path", path = "project/path", proto = "ssh", repo = "repo", repository = "repo", url = "ssh://git@gitlab.priv/project/path/repo.git", user = "git" } { host = "gitlab.priv", owner = "project/path", path = "project/path", port = "2222", proto = "ssh", repo = "repo", repository = "repo", url = "ssh://git@gitlab.priv:2222/project/path/repo.git", user = "git" } { host = "gitlab.priv", owner = "project/path", path = "project/path", port = "2222", proto = "ssh", repo = "repo", repository = "repo", url = "ssh://git:pass@gitlab.priv:2222/project/path/repo.git", user = "git" } { host = "gitlab.priv", owner = "project/path", path = "project/path", proto = "https", repo = "repo", repository = "repo", url = "https://gitlab.priv/project/path/repo.git" } { host = "gitlab.priv", owner = "project/path", path = "project/path", port = "4443", proto = "https", repo = "repo", repository = "repo", url = "https://gitlab.priv:4443/project/path/repo.git" } ```

And now it works as expected with the following configuration:

      git_services = {
        ["github.com"] = "https://github.com/${owner}/${repository}/compare/${branch_name}?expand=1",
        ["gitlab.com"] = "https://gitlab.com/${owner}/${repository}/merge_requests/new?merge_request[source_branch]=${branch_name}",
        ["gitlab.priv"] = "https://gitlab.priv/${path}/${repository}/-/merge_requests/new?merge_request[source_branch]=${branch_name}&merge_request[target_branch]=main",
      },

Lastly, the test are passing to the same extent they were before this patch.

CKolkey commented 6 months ago

I dig it. Nice work.