From 85afbbc2ed36945adeaf6fa09f6066a549631a6f Mon Sep 17 00:00:00 2001 From: Andrew He Date: Thu, 15 Jun 2017 12:15:02 -0700 Subject: [PATCH] Fix shallow git clone in docker-build If the HEAD request fails, use a GET request to properly test if git server is smart-http. Signed-off-by: Andrew He --- builder/remotecontext/git/gitutils.go | 43 ++++++++++++++++++++------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/builder/remotecontext/git/gitutils.go b/builder/remotecontext/git/gitutils.go index b94d462cd5..7bc2268155 100644 --- a/builder/remotecontext/git/gitutils.go +++ b/builder/remotecontext/git/gitutils.go @@ -1,7 +1,6 @@ package git import ( - "fmt" "io/ioutil" "net/http" "net/url" @@ -98,22 +97,46 @@ func getRefAndSubdir(fragment string) (ref string, subdir string) { func fetchArgs(remoteURL string, ref string) []string { args := []string{"fetch", "--recurse-submodules=yes"} - shallow := true - if urlutil.IsURL(remoteURL) { - res, err := http.Head(fmt.Sprintf("%s/info/refs?service=git-upload-pack", remoteURL)) - if err != nil || res.Header.Get("Content-Type") != "application/x-git-upload-pack-advertisement" { - shallow = false - } - } - - if shallow { + if supportsShallowClone(remoteURL) { args = append(args, "--depth", "1") } return append(args, "origin", ref) } +// Check if a given git URL supports a shallow git clone, +// i.e. it is a non-HTTP server or a smart HTTP server. +func supportsShallowClone(remoteURL string) bool { + if urlutil.IsURL(remoteURL) { + // Check if the HTTP server is smart + + // Smart servers must correctly respond to a query for the git-upload-pack service + serviceURL := remoteURL + "/info/refs?service=git-upload-pack" + + // Try a HEAD request and fallback to a Get request on error + res, err := http.Head(serviceURL) + if err != nil || res.StatusCode != http.StatusOK { + res, err = http.Get(serviceURL) + if err == nil { + res.Body.Close() + } + if err != nil || res.StatusCode != http.StatusOK { + // request failed + return false + } + } + + if res.Header.Get("Content-Type") != "application/x-git-upload-pack-advertisement" { + // Fallback, not a smart server + return false + } + return true + } + // Non-HTTP protocols always support shallow clones + return true +} + func checkoutGit(root, ref, subdir string) (string, error) { // Try checking out by ref name first. This will work on branches and sets // .git/HEAD to the current branch name