gitgoazure-devopsgo-git

git repo url is appended with /git-upload-pack on using go-git's Plainclone function


Trying to clone a repo from Azure devops.

func (gitopt *GitOptions) clone() (*git.Repository, error) {
    r, err := git.PlainClone(gitopt.RepoDir, false, &git.CloneOptions{
        Progress: os.Stdout,
        URL:      "https://<path to repo>",
        Auth: &http.BasicAuth{
            Username: "gituser",
            Password: gitopt.PAT,
        },
    })
    if err != nil {
        log.Info(err.Error())
        return nil, err
    }

    return r, nil
}

Running this code is adding /git-upload-pack at the end of repo url ("https://<path to repo>/git-upload-pack") due to which clone is failing with status code 400. Couldn't understand why this is being appended.


Solution

  • The Git protocol over HTTP consists of two steps, which vary depending on the version of the protocol in use. In v0 and v1, the first request is to /info/refs and reads the refs in use, and then the second request is to either /git-upload-pack (for fetches and clones) or /git-receive-pack (for pushes). In v2, the endpoints are the same, but the first is a capability request, and then the ref request and data transfer are made to the second endpoint.

    In all of these cases, the URL that you've provided is merely a base from which the paths are appended. The different paths make access control easier for simple Git servers behind something like nginx or Apache, which is why there's not just a single URL component.

    So the URL that's being generated is in fact correct. The reason you're seeing a 400 is because of an issue in which Azure DevOps requires clients to support the multi_ack capability, which go-git does not. While technically servers don't have to provide support to any clients they don't want to, the Git smart HTTP protocol is typically designed to degrade gracefully, so it isn't a safe assumption that a client will necessarily support any specific set of features, and Azure DevOps should avoid making that assumption.

    The linked issue has a link to a pull request that fixes the problem in some, but not all, cases. You may need to update to a later version to take advantage of that, though.