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>
| ... | ... |
@@ -1,7 +1,6 @@ |
| 1 | 1 |
package git |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "fmt" |
|
| 5 | 4 |
"io/ioutil" |
| 6 | 5 |
"net/http" |
| 7 | 6 |
"net/url" |
| ... | ... |
@@ -98,22 +97,46 @@ func getRefAndSubdir(fragment string) (ref string, subdir string) {
|
| 98 | 98 |
|
| 99 | 99 |
func fetchArgs(remoteURL string, ref string) []string {
|
| 100 | 100 |
args := []string{"fetch", "--recurse-submodules=yes"}
|
| 101 |
- shallow := true |
|
| 102 | 101 |
|
| 103 |
- if urlutil.IsURL(remoteURL) {
|
|
| 104 |
- res, err := http.Head(fmt.Sprintf("%s/info/refs?service=git-upload-pack", remoteURL))
|
|
| 105 |
- if err != nil || res.Header.Get("Content-Type") != "application/x-git-upload-pack-advertisement" {
|
|
| 106 |
- shallow = false |
|
| 107 |
- } |
|
| 108 |
- } |
|
| 109 |
- |
|
| 110 |
- if shallow {
|
|
| 102 |
+ if supportsShallowClone(remoteURL) {
|
|
| 111 | 103 |
args = append(args, "--depth", "1") |
| 112 | 104 |
} |
| 113 | 105 |
|
| 114 | 106 |
return append(args, "origin", ref) |
| 115 | 107 |
} |
| 116 | 108 |
|
| 109 |
+// Check if a given git URL supports a shallow git clone, |
|
| 110 |
+// i.e. it is a non-HTTP server or a smart HTTP server. |
|
| 111 |
+func supportsShallowClone(remoteURL string) bool {
|
|
| 112 |
+ if urlutil.IsURL(remoteURL) {
|
|
| 113 |
+ // Check if the HTTP server is smart |
|
| 114 |
+ |
|
| 115 |
+ // Smart servers must correctly respond to a query for the git-upload-pack service |
|
| 116 |
+ serviceURL := remoteURL + "/info/refs?service=git-upload-pack" |
|
| 117 |
+ |
|
| 118 |
+ // Try a HEAD request and fallback to a Get request on error |
|
| 119 |
+ res, err := http.Head(serviceURL) |
|
| 120 |
+ if err != nil || res.StatusCode != http.StatusOK {
|
|
| 121 |
+ res, err = http.Get(serviceURL) |
|
| 122 |
+ if err == nil {
|
|
| 123 |
+ res.Body.Close() |
|
| 124 |
+ } |
|
| 125 |
+ if err != nil || res.StatusCode != http.StatusOK {
|
|
| 126 |
+ // request failed |
|
| 127 |
+ return false |
|
| 128 |
+ } |
|
| 129 |
+ } |
|
| 130 |
+ |
|
| 131 |
+ if res.Header.Get("Content-Type") != "application/x-git-upload-pack-advertisement" {
|
|
| 132 |
+ // Fallback, not a smart server |
|
| 133 |
+ return false |
|
| 134 |
+ } |
|
| 135 |
+ return true |
|
| 136 |
+ } |
|
| 137 |
+ // Non-HTTP protocols always support shallow clones |
|
| 138 |
+ return true |
|
| 139 |
+} |
|
| 140 |
+ |
|
| 117 | 141 |
func checkoutGit(root, ref, subdir string) (string, error) {
|
| 118 | 142 |
// Try checking out by ref name first. This will work on branches and sets |
| 119 | 143 |
// .git/HEAD to the current branch name |