chore: Refactored LocalClone function 6f4150c7
Steve · 2024-08-21 20:39 1 file(s) · +151 −0
LocalClone.go (added) +151 −0
1 +
package main
2 +
3 +
import (
4 +
	"flag"
5 +
	"fmt"
6 +
	"os"
7 +
	"os/exec"
8 +
	"os/signal"
9 +
	"path/filepath"
10 +
	"syscall"
11 +
12 +
	"github.com/AlecAivazis/survey/v2"
13 +
	"github.com/fatih/color"
14 +
)
15 +
16 +
type Repo struct {
17 +
	Path string
18 +
	Name string
19 +
}
20 +
21 +
var isPrivate bool
22 +
23 +
func LocalClone() error {
24 +
	flag.BoolVar(&isPrivate, "private", false, "Initialize repositories as private")
25 +
	flag.Parse()
26 +
27 +
	repos := findGitRepos(".")
28 +
	selectedRepos := selectRepos(repos)
29 +
	confirmAndInitRepos(selectedRepos)
30 +
	return nil
31 +
}
32 +
33 +
func findGitRepos(root string) []Repo {
34 +
	var repos []Repo
35 +
	var scannedDirs int
36 +
37 +
	entries, err := os.ReadDir(root)
38 +
	if err != nil {
39 +
		fmt.Printf("Error reading directory %v: %v\n", root, err)
40 +
		return repos
41 +
	}
42 +
43 +
	for _, entry := range entries {
44 +
		if !entry.IsDir() {
45 +
			continue
46 +
		}
47 +
48 +
		scannedDirs++
49 +
		fmt.Printf("\rScanned %d directories...", scannedDirs)
50 +
51 +
		dirPath := filepath.Join(root, entry.Name())
52 +
		gitDir := filepath.Join(dirPath, ".git")
53 +
54 +
		if _, err := os.Stat(gitDir); err == nil {
55 +
			repos = append(repos, Repo{
56 +
				Path: dirPath,
57 +
				Name: entry.Name(),
58 +
			})
59 +
		}
60 +
	}
61 +
62 +
	// Clear the progress line and print final count
63 +
	fmt.Printf("\rScanned %d directories. Found %d Git repositories.\n", scannedDirs, len(repos))
64 +
65 +
	return repos
66 +
}
67 +
68 +
func selectRepos(repos []Repo) []Repo {
69 +
	var options []string
70 +
	for _, repo := range repos {
71 +
		options = append(options, repo.Name)
72 +
	}
73 +
74 +
	var selected []string
75 +
	prompt := &survey.MultiSelect{
76 +
		Message: "Select repositories to initialize:",
77 +
		Options: options,
78 +
	}
79 +
	survey.AskOne(prompt, &selected)
80 +
81 +
	var selectedRepos []Repo
82 +
	for _, name := range selected {
83 +
		for _, repo := range repos {
84 +
			if repo.Name == name {
85 +
				selectedRepos = append(selectedRepos, repo)
86 +
				break
87 +
			}
88 +
		}
89 +
	}
90 +
91 +
	return selectedRepos
92 +
}
93 +
94 +
func confirmAndInitRepos(repos []Repo) {
95 +
	visibilityStr := "public"
96 +
	if isPrivate {
97 +
		visibilityStr = "private"
98 +
	}
99 +
100 +
	confirm := false
101 +
	prompt := &survey.Confirm{
102 +
		Message: fmt.Sprintf("Initialize %d repositories as %s?", len(repos), visibilityStr),
103 +
	}
104 +
	survey.AskOne(prompt, &confirm)
105 +
106 +
	if !confirm {
107 +
		fmt.Println("Radicalization cancelled.")
108 +
		return
109 +
	}
110 +
111 +
	fmt.Printf("Initializing %d repositories as %s...\n", len(repos), visibilityStr)
112 +
113 +
	interrupt := make(chan os.Signal, 1)
114 +
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
115 +
116 +
	done := make(chan bool)
117 +
118 +
	go func() {
119 +
		for i, repo := range repos {
120 +
			select {
121 +
			case <-interrupt:
122 +
				fmt.Println("\nInterrupted. Stopping initialization process.")
123 +
				done <- true
124 +
				return
125 +
			default:
126 +
				fmt.Printf("Initializing %s (%d/%d)...\n", repo.Name, i+1, len(repos))
127 +
				err := runRadInit(repo.Path, repo.Name)
128 +
				if err != nil {
129 +
					color.Red("Error initializing %s: %v\n", repo.Name, err)
130 +
				} else {
131 +
					color.Green("Initialized %s as %s\n", repo.Name, visibilityStr)
132 +
				}
133 +
			}
134 +
		}
135 +
		done <- true
136 +
	}()
137 +
138 +
	<-done
139 +
	fmt.Println("Radicalization Complete")
140 +
}
141 +
142 +
func runRadInit(path, name string) error {
143 +
	visibilityFlag := "--public"
144 +
	if isPrivate {
145 +
		visibilityFlag = "--private"
146 +
	}
147 +
148 +
	cmd := exec.Command("rad", "init", "--name", name, "--description", "", visibilityFlag, "--no-confirm")
149 +
	cmd.Dir = path
150 +
	return cmd.Run()
151 +
}