init 2cd5dbd9
Steve · 2024-08-16 11:32 4 file(s) · +231 −0
.gitignore (added) +1 −0
1 +
radicalize
go.mod (added) +16 −0
1 +
module github.com/stevedylandev/radicalize
2 +
3 +
go 1.22.6
4 +
5 +
require (
6 +
	github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
7 +
	github.com/briandowns/spinner v1.23.1 // indirect
8 +
	github.com/fatih/color v1.17.0 // indirect
9 +
	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
10 +
	github.com/mattn/go-colorable v0.1.13 // indirect
11 +
	github.com/mattn/go-isatty v0.0.20 // indirect
12 +
	github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
13 +
	golang.org/x/sys v0.18.0 // indirect
14 +
	golang.org/x/term v0.1.0 // indirect
15 +
	golang.org/x/text v0.4.0 // indirect
16 +
)
go.sum (added) +65 −0
1 +
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
2 +
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
3 +
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
4 +
github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650=
5 +
github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM=
6 +
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
7 +
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8 +
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
9 +
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
10 +
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
11 +
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
12 +
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
13 +
github.com/hinshun/vt10x v0.0.0-20220119200601-820417d04eec/go.mod h1:Q48J4R4DvxnHolD5P8pOtXigYlRuPLGl6moFx3ulM68=
14 +
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
15 +
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
16 +
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
17 +
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
18 +
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
19 +
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
20 +
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
21 +
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
22 +
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
23 +
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
24 +
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
25 +
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
26 +
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
27 +
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
28 +
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
29 +
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
30 +
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
31 +
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
32 +
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
33 +
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
34 +
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
35 +
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
36 +
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
37 +
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
38 +
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
39 +
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
40 +
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
41 +
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
42 +
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
43 +
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
44 +
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s=
45 +
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
46 +
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
47 +
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
48 +
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
49 +
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
50 +
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
51 +
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
52 +
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
53 +
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
54 +
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
55 +
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
56 +
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
57 +
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
58 +
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
59 +
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
60 +
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
61 +
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
62 +
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
63 +
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
64 +
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
65 +
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
main.go (added) +149 −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 +
	"time"
12 +
13 +
	"github.com/AlecAivazis/survey/v2"
14 +
	"github.com/briandowns/spinner"
15 +
	"github.com/fatih/color"
16 +
)
17 +
18 +
type Repo struct {
19 +
	Path string
20 +
	Name string
21 +
}
22 +
23 +
var isPrivate bool
24 +
25 +
func main() {
26 +
	flag.BoolVar(&isPrivate, "private", false, "Initialize repositories as private")
27 +
	flag.Parse()
28 +
29 +
	repos := findGitRepos(".")
30 +
	selectedRepos := selectRepos(repos)
31 +
	confirmAndInitRepos(selectedRepos)
32 +
}
33 +
34 +
func findGitRepos(root string) []Repo {
35 +
	var repos []Repo
36 +
37 +
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
38 +
		if err != nil {
39 +
			return err
40 +
		}
41 +
		if info.IsDir() && info.Name() == ".git" {
42 +
			repoPath := filepath.Dir(path)
43 +
			repos = append(repos, Repo{
44 +
				Path: repoPath,
45 +
				Name: filepath.Base(repoPath),
46 +
			})
47 +
			return filepath.SkipDir
48 +
		}
49 +
		return nil
50 +
	})
51 +
52 +
	if err != nil {
53 +
		fmt.Printf("Error walking the path %v: %v\n", root, err)
54 +
	}
55 +
56 +
	return repos
57 +
}
58 +
59 +
func selectRepos(repos []Repo) []Repo {
60 +
	var options []string
61 +
	for _, repo := range repos {
62 +
		options = append(options, repo.Name)
63 +
	}
64 +
65 +
	var selected []string
66 +
	prompt := &survey.MultiSelect{
67 +
		Message: "Select repositories to initialize:",
68 +
		Options: options,
69 +
	}
70 +
	survey.AskOne(prompt, &selected)
71 +
72 +
	var selectedRepos []Repo
73 +
	for _, name := range selected {
74 +
		for _, repo := range repos {
75 +
			if repo.Name == name {
76 +
				selectedRepos = append(selectedRepos, repo)
77 +
				break
78 +
			}
79 +
		}
80 +
	}
81 +
82 +
	return selectedRepos
83 +
}
84 +
85 +
func confirmAndInitRepos(repos []Repo) {
86 +
	visibilityStr := "public"
87 +
	if isPrivate {
88 +
		visibilityStr = "private"
89 +
	}
90 +
91 +
	confirm := false
92 +
	prompt := &survey.Confirm{
93 +
		Message: fmt.Sprintf("Initialize %d repositories as %s?", len(repos), visibilityStr),
94 +
	}
95 +
	survey.AskOne(prompt, &confirm)
96 +
97 +
	if !confirm {
98 +
		fmt.Println("Operation cancelled.")
99 +
		return
100 +
	}
101 +
102 +
	s := spinner.New(spinner.CharSets[9], 100*time.Millisecond)
103 +
	s.Prefix = "Initializing repositories "
104 +
	s.Start()
105 +
106 +
	// Set up channel to listen for interrupt signal
107 +
	interrupt := make(chan os.Signal, 1)
108 +
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
109 +
110 +
	// Create a done channel to signal completion
111 +
	done := make(chan bool)
112 +
113 +
	go func() {
114 +
		for i, repo := range repos {
115 +
			select {
116 +
			case <-interrupt:
117 +
				fmt.Println("\nInterrupted. Stopping initialization process.")
118 +
				done <- true
119 +
				return
120 +
			default:
121 +
				err := runRadInit(repo.Path, repo.Name)
122 +
				if err != nil {
123 +
					color.Red("Error initializing %s: %v\n", repo.Name, err)
124 +
				} else {
125 +
					color.Green("Initialized %s as %s\n", repo.Name, visibilityStr)
126 +
				}
127 +
				s.Suffix = fmt.Sprintf(" (%d/%d)", i+1, len(repos))
128 +
			}
129 +
		}
130 +
		done <- true
131 +
	}()
132 +
133 +
	<-done
134 +
	s.Stop()
135 +
	fmt.Println("Initialization process completed or interrupted.")
136 +
}
137 +
138 +
func runRadInit(path, name string) error {
139 +
	visibilityFlag := "--public"
140 +
	if isPrivate {
141 +
		visibilityFlag = "--private"
142 +
	}
143 +
144 +
	cmd := exec.Command("rad", "init", "--name", name, "--description", "", visibilityFlag, "--no-confirm")
145 +
	cmd.Dir = path
146 +
	// cmd.Stdout = os.Stdout
147 +
	// cmd.Stderr = os.Stderr
148 +
	return cmd.Run()
149 +
}