Explorar o código

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 <he.andrew.mail@gmail.com>
Andrew He %!s(int64=8) %!d(string=hai) anos
pai
achega
85afbbc2ed
Modificáronse 1 ficheiros con 33 adicións e 10 borrados
  1. 33 10
      builder/remotecontext/git/gitutils.go

+ 33 - 10
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