CloneRepo clone git repo.
(title, target, repoUrl, repoRef string, depth int, repoDir string)
| 17 | |
| 18 | // CloneRepo clone git repo. |
| 19 | func CloneRepo(title, target, repoUrl, repoRef string, depth int, repoDir string) error { |
| 20 | retryExecutor := func(title, command string) error { |
| 21 | executor := cmd.NewExecutor(title, command) |
| 22 | if fileio.PathExists(repoDir) { |
| 23 | executor.SetWorkDir(repoDir) |
| 24 | } |
| 25 | return executor.Execute() |
| 26 | } |
| 27 | |
| 28 | cloneArgsFunc := func(repoRef, repoUrl, repoDir string, depth int) []string { |
| 29 | args := []string{"clone"} |
| 30 | if repoRef != "" { |
| 31 | args = append(args, "--branch", repoRef) |
| 32 | } |
| 33 | if depth > 0 { |
| 34 | args = append(args, "--single-branch") |
| 35 | args = append(args, "--depth", fmt.Sprint(depth)) |
| 36 | } |
| 37 | args = append(args, repoUrl, repoDir) |
| 38 | return args |
| 39 | } |
| 40 | |
| 41 | cloneWithRetry := func(action string, args []string) error { |
| 42 | var lastErr error |
| 43 | |
| 44 | for attempt := 1; attempt <= retryMaxAttempts; attempt++ { |
| 45 | // Failed clones can leave a partial destination behind and poison the |
| 46 | // next attempt, so always retry from a clean target directory. |
| 47 | if err := os.RemoveAll(repoDir); err != nil { |
| 48 | return fmt.Errorf("failed to clean repo dir %s for %s -> %w", repoDir, target, err) |
| 49 | } |
| 50 | |
| 51 | executor := cmd.NewExecutor(title, "git", args...) |
| 52 | err := executor.Execute() |
| 53 | if err == nil { |
| 54 | return nil |
| 55 | } |
| 56 | |
| 57 | lastErr = err |
| 58 | color.Printf(color.Warning, "Git %s failed (attempt %d/%d) for %s: %v\n", action, attempt, retryMaxAttempts, target, err) |
| 59 | if attempt < retryMaxAttempts { |
| 60 | retrySleep(attempt) |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | return fmt.Errorf("git %s failed after %d attempts for %s -> %w", action, retryMaxAttempts, target, lastErr) |
| 65 | } |
| 66 | |
| 67 | cloneWithFallback := func(action string, repoRef string, depth int) error { |
| 68 | args := cloneArgsFunc(repoRef, repoUrl, repoDir, depth) |
| 69 | if err := cloneWithRetry(action, args); err != nil { |
| 70 | if depth > 0 { |
| 71 | color.Printf(color.Warning, "-- Git %s failed with shallow clone for %s, retrying without --depth\n", action, target) |
| 72 | if fallbackErr := cloneWithRetry(action+" without depth", cloneArgsFunc(repoRef, repoUrl, repoDir, 0)); fallbackErr == nil { |
| 73 | return nil |
| 74 | } |
| 75 | } |
| 76 | return err |