github.com/squaremo/docker@v1.3.2-0.20150516120342-42cfc9554972/utils/git.go (about) 1 package utils 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "net/url" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strings" 12 13 "github.com/docker/docker/pkg/urlutil" 14 ) 15 16 func GitClone(remoteURL string) (string, error) { 17 if !urlutil.IsGitTransport(remoteURL) { 18 remoteURL = "https://" + remoteURL 19 } 20 root, err := ioutil.TempDir("", "docker-build-git") 21 if err != nil { 22 return "", err 23 } 24 25 u, err := url.Parse(remoteURL) 26 if err != nil { 27 return "", err 28 } 29 30 fragment := u.Fragment 31 clone := cloneArgs(u, root) 32 33 if output, err := git(clone...); err != nil { 34 return "", fmt.Errorf("Error trying to use git: %s (%s)", err, output) 35 } 36 37 return checkoutGit(fragment, root) 38 } 39 40 func cloneArgs(remoteURL *url.URL, root string) []string { 41 args := []string{"clone", "--recursive"} 42 shallow := len(remoteURL.Fragment) == 0 43 44 if shallow && strings.HasPrefix(remoteURL.Scheme, "http") { 45 res, err := http.Head(fmt.Sprintf("%s/info/refs?service=git-upload-pack", remoteURL)) 46 if err != nil || res.Header.Get("Content-Type") != "application/x-git-upload-pack-advertisement" { 47 shallow = false 48 } 49 } 50 51 if shallow { 52 args = append(args, "--depth", "1") 53 } 54 55 if remoteURL.Fragment != "" { 56 remoteURL.Fragment = "" 57 } 58 59 return append(args, remoteURL.String(), root) 60 } 61 62 func checkoutGit(fragment, root string) (string, error) { 63 refAndDir := strings.SplitN(fragment, ":", 2) 64 65 if len(refAndDir[0]) != 0 { 66 if output, err := gitWithinDir(root, "checkout", refAndDir[0]); err != nil { 67 return "", fmt.Errorf("Error trying to use git: %s (%s)", err, output) 68 } 69 } 70 71 if len(refAndDir) > 1 && len(refAndDir[1]) != 0 { 72 newCtx := filepath.Join(root, refAndDir[1]) 73 fi, err := os.Stat(newCtx) 74 if err != nil { 75 return "", err 76 } 77 if !fi.IsDir() { 78 return "", fmt.Errorf("Error setting git context, not a directory: %s", newCtx) 79 } 80 root = newCtx 81 } 82 83 return root, nil 84 } 85 86 func gitWithinDir(dir string, args ...string) ([]byte, error) { 87 a := []string{"--work-tree", dir, "--git-dir", filepath.Join(dir, ".git")} 88 return git(append(a, args...)...) 89 } 90 91 func git(args ...string) ([]byte, error) { 92 return exec.Command("git", args...).CombinedOutput() 93 }