github.com/Cloud-Foundations/Dominator@v0.3.4/lib/gitutil/shallowClone.go (about) 1 package gitutil 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os" 8 "os/exec" 9 "path" 10 "path/filepath" 11 "strings" 12 "time" 13 14 "github.com/Cloud-Foundations/Dominator/lib/format" 15 "github.com/Cloud-Foundations/Dominator/lib/fsutil" 16 "github.com/Cloud-Foundations/Dominator/lib/log" 17 "github.com/Cloud-Foundations/Dominator/lib/stringutil" 18 ) 19 20 func gitGrab(topdir string, gitBranch string, logger log.DebugLogger) error { 21 if gitBranch == "" { 22 return runCommand(logger, topdir, "git", "pull", "--depth=1", "origin", 23 "") 24 } 25 err := runCommand(logger, topdir, "git", "fetch", "--depth=1", "origin") 26 if err != nil { 27 return err 28 } 29 branchList, err := fsutil.ReadDirnames(filepath.Join(topdir, ".git", "refs", 30 "remotes", "origin"), false) 31 if err != nil { 32 return err 33 } 34 branchMap := stringutil.ConvertListToMap(branchList, false) 35 var branchToMerge string 36 if _, ok := branchMap[gitBranch]; ok { 37 branchToMerge = gitBranch 38 } else { 39 branchToMerge = branchList[0] 40 } 41 err = runCommand(logger, topdir, "git", "merge", 42 path.Join("origin", branchToMerge)) 43 if err != nil { 44 return err 45 } 46 if gitBranch != "" && branchToMerge != gitBranch { 47 err := runCommand(logger, topdir, "git", "fetch", "--unshallow", 48 "origin") 49 if err != nil { 50 return err 51 } 52 err = runCommand(logger, topdir, "git", "checkout", gitBranch) 53 if err != nil { 54 return err 55 } 56 } 57 return nil 58 } 59 60 func runCommand(logger log.DebugLogger, cwd string, args ...string) error { 61 cmd := exec.Command(args[0], args[1:]...) 62 cmd.Dir = cwd 63 if writer, ok := logger.(io.Writer); ok { 64 cmd.Stdout = writer 65 cmd.Stderr = writer 66 return cmd.Run() 67 } 68 if _output, err := cmd.CombinedOutput(); err != nil { 69 output := strings.TrimSpace(string(_output)) 70 if len(output) < 1 { 71 return fmt.Errorf("error running: %s %s: %s", args[0], args[1], err) 72 } 73 return fmt.Errorf("error running: %s %s: %s: %s", 74 args[0], args[1], err, output) 75 } 76 return nil 77 } 78 79 func shallowClone(topdir string, params ShallowCloneParams, 80 logger log.DebugLogger) error { 81 if params.PublicURL == "" { 82 params.PublicURL = params.RepoURL 83 } 84 if params.GitBranch != "" { 85 logger.Debugf(0, "Cloning repository: %s branch: %s\n", 86 params.PublicURL, params.GitBranch) 87 } else { 88 logger.Debugf(0, "Cloning repository: %s\n", params.PublicURL) 89 } 90 startTime := time.Now() 91 err := runCommand(logger, "", "git", "init", "-b", "master", topdir) 92 if err != nil { 93 return err 94 } 95 err = runCommand(logger, topdir, "git", "remote", "add", "origin", 96 params.RepoURL) 97 if err != nil { 98 return err 99 } 100 if len(params.Patterns) > 0 { 101 err := runCommand(logger, topdir, "git", "config", 102 "core.sparsecheckout", "true") 103 if err != nil { 104 return err 105 } 106 file, err := os.Create( 107 filepath.Join(topdir, ".git", "info", "sparse-checkout")) 108 if err != nil { 109 return err 110 } 111 defer file.Close() 112 writer := bufio.NewWriter(file) 113 defer writer.Flush() 114 for _, pattern := range params.Patterns { 115 fmt.Fprintln(writer, pattern) 116 } 117 if err := writer.Flush(); err != nil { 118 return err 119 } 120 } 121 if err := gitGrab(topdir, params.GitBranch, logger); err != nil { 122 return err 123 } 124 loadTime := time.Since(startTime) 125 repoSize, err := fsutil.GetTreeSize(topdir) 126 if err != nil { 127 return err 128 } 129 speed := float64(repoSize) / loadTime.Seconds() 130 logger.Debugf(0, 131 "Downloaded partial repository in %s, size: %s (%s/s)\n", 132 format.Duration(loadTime), format.FormatBytes(repoSize), 133 format.FormatBytes(uint64(speed))) 134 return nil 135 }