diff --git a/cmd/clone.go b/cmd/clone.go index 993c44bc31..563b26f90c 100644 --- a/cmd/clone.go +++ b/cmd/clone.go @@ -1,7 +1,6 @@ package cmd import ( - "context" "fmt" "os" "os/exec" @@ -11,16 +10,16 @@ import ( "github.com/spf13/cobra" "github.com/gabrie30/ghorg/colorlog" - "github.com/google/go-github/github" - "golang.org/x/oauth2" ) var ( - protocol string - path string - branch string - token string - args []string + protocol string + path string + branch string + token string + cloneType string + scmType string + args []string ) func init() { @@ -29,6 +28,10 @@ func init() { cloneCmd.Flags().StringVarP(&path, "path", "p", "", "absolute path the ghorg_* directory will be created (defaults to Desktop)") cloneCmd.Flags().StringVarP(&branch, "branch", "b", "", "branch left checked out for each repo cloned (defaults to master)") cloneCmd.Flags().StringVarP(&token, "token", "t", "", "github token to clone with") + + cloneCmd.Flags().StringVarP(&scmType, "scm", "s", "github", "type of scm used, github or gitlab") + // TODO: make gitlab terminology make sense https://about.gitlab.com/2016/01/27/comparing-terms-gitlab-github-bitbucket/ + cloneCmd.Flags().StringVarP(&cloneType, "clone_type", "c", "org", "clone target type, user or org") } var cloneCmd = &cobra.Command{ @@ -64,94 +67,65 @@ var cloneCmd = &cobra.Command{ os.Setenv("GHORG_GITHUB_TOKEN", cmd.Flag("token").Value.String()) } + if cmd.Flags().Changed("clone_type") { + cloneType := strings.ToLower(cmd.Flag("clone_type").Value.String()) + if cloneType != "user" && cloneType != "org" { + colorlog.PrintError("clone_type must be one of org or user") + os.Exit(1) + } + os.Setenv("GHORG_CLONE_TYPE", cloneType) + } + + if cmd.Flags().Changed("scm") { + scmType := strings.ToLower(cmd.Flag("scm").Value.String()) + fmt.Println(scmType) + if scmType != "github" && scmType != "gitlab" { + colorlog.PrintError("scm must be one of github or gitlab") + os.Exit(1) + } + os.Setenv("GHORG_SCM_TYPE", scmType) + } + args = argz - CloneAllReposByOrg() + CloneAllRepos() }, } // TODO: Figure out how to use go channels for this func getAllOrgCloneUrls() ([]string, error) { asciiTime() - ctx := context.Background() - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: os.Getenv("GHORG_GITHUB_TOKEN")}, - ) - tc := oauth2.NewClient(ctx, ts) - client := github.NewClient(tc) - - opt := &github.RepositoryListByOrgOptions{ - Type: "all", - ListOptions: github.ListOptions{PerPage: 100, Page: 0}, - } - - // get all pages of results - var allRepos []*github.Repository - for { - repos, resp, err := client.Repositories.ListByOrg(context.Background(), args[0], opt) - - if err != nil { - return nil, err - } - allRepos = append(allRepos, repos...) - if resp.NextPage == 0 { - break - } - opt.Page = resp.NextPage - } - cloneUrls := []string{} - - for _, repo := range allRepos { - if os.Getenv("GHORG_CLONE_PROTOCOL") == "https" { - cloneUrls = append(cloneUrls, *repo.CloneURL) - } else { - cloneUrls = append(cloneUrls, *repo.SSHURL) - } + var urls []string + var err error + switch os.Getenv("GHORG_SCM_TYPE") { + case "github": + urls, err = getGitHubOrgCloneUrls() + case "gitlab": + urls, err = getGitLabOrgCloneUrls() + default: + colorlog.PrintError("GHORG_SCM_TYPE not set or unsupported") + os.Exit(1) } - return cloneUrls, nil + return urls, err } -// TODO: refactor with getAllOrgCloneUrls +// TODO: Figure out how to use go channels for this func getAllUserCloneUrls() ([]string, error) { - ctx := context.Background() - - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: os.Getenv("GHORG_GITHUB_TOKEN")}, - ) - tc := oauth2.NewClient(ctx, ts) - client := github.NewClient(tc) - - opt := &github.RepositoryListOptions{ - Type: "all", - ListOptions: github.ListOptions{PerPage: 100, Page: 0}, - } - - // get all pages of results - var allRepos []*github.Repository - for { - repos, resp, err := client.Repositories.List(context.Background(), args[0], opt) - - if err != nil { - return nil, err - } - allRepos = append(allRepos, repos...) - if resp.NextPage == 0 { - break - } - opt.Page = resp.NextPage - } - cloneUrls := []string{} - - for _, repo := range allRepos { - if os.Getenv("GHORG_CLONE_PROTOCOL") == "https" { - cloneUrls = append(cloneUrls, *repo.CloneURL) - } else { - cloneUrls = append(cloneUrls, *repo.SSHURL) - } + asciiTime() + var urls []string + var err error + switch os.Getenv("GHORG_SCM_TYPE") { + case "github": + urls, err = getGitHubUserCloneUrls() + case "gitlab": + urls, err = getGitLabUserCloneUrls() + default: + colorlog.PrintError("GHORG_SCM_TYPE not set or unsupported") + os.Exit(1) } - return cloneUrls, nil + return urls, err } func createDirIfNotExist() { @@ -200,8 +174,8 @@ func printRemainingMessages(infoMessages []error, errors []error) { } } -// CloneAllReposByOrg clones all repos for a given org -func CloneAllReposByOrg() { +// CloneAllRepos clones all repos +func CloneAllRepos() { resc, errc, infoc := make(chan string), make(chan error), make(chan error) createDirIfNotExist() @@ -214,16 +188,21 @@ func CloneAllReposByOrg() { fmt.Println() } - cloneTargets, err := getAllOrgCloneUrls() + var cloneTargets []string + var err error - if err != nil { - colorlog.PrintSubtleInfo("Change of Plans! Did not find GitHub Org " + args[0] + " -- Looking instead for a GitHub User: " + args[0]) - fmt.Println() + if os.Getenv("GHORG_CLONE_TYPE") == "org" { + cloneTargets, err = getAllOrgCloneUrls() + } else if os.Getenv("GHORG_CLONE_TYPE") == "user" { cloneTargets, err = getAllUserCloneUrls() + } else { + colorlog.PrintError("GHORG_CLONE_TYPE not set or unsupported") + os.Exit(1) } if err != nil { - colorlog.PrintError(err) + colorlog.PrintSubtleInfo("Did not find " + os.Getenv("GHORG_SCM_TYPE") + " " + os.Getenv("GHORG_CLONE_TYPE") + ": " + args[0] + ", check spelling and try again.") + fmt.Println() os.Exit(1) } else { colorlog.PrintInfo(strconv.Itoa(len(cloneTargets)) + " repos found in " + args[0]) diff --git a/cmd/clone_github.go b/cmd/clone_github.go new file mode 100644 index 0000000000..2b224044c2 --- /dev/null +++ b/cmd/clone_github.go @@ -0,0 +1,92 @@ +package cmd + +import ( + "context" + "os" + + "github.com/google/go-github/github" + "golang.org/x/oauth2" +) + +func getGitHubOrgCloneUrls() ([]string, error) { + + ctx := context.Background() + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: os.Getenv("GHORG_GITHUB_TOKEN")}, + ) + tc := oauth2.NewClient(ctx, ts) + client := github.NewClient(tc) + + opt := &github.RepositoryListByOrgOptions{ + Type: "all", + ListOptions: github.ListOptions{PerPage: 100, Page: 0}, + } + + // get all pages of results + var allRepos []*github.Repository + for { + repos, resp, err := client.Repositories.ListByOrg(context.Background(), args[0], opt) + + if err != nil { + return nil, err + } + allRepos = append(allRepos, repos...) + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + cloneUrls := []string{} + + for _, repo := range allRepos { + if os.Getenv("GHORG_CLONE_PROTOCOL") == "https" { + cloneUrls = append(cloneUrls, *repo.CloneURL) + } else { + cloneUrls = append(cloneUrls, *repo.SSHURL) + } + } + + return cloneUrls, nil +} + +// TODO: refactor with getAllOrgCloneUrls +func getGitHubUserCloneUrls() ([]string, error) { + ctx := context.Background() + + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: os.Getenv("GHORG_GITHUB_TOKEN")}, + ) + tc := oauth2.NewClient(ctx, ts) + client := github.NewClient(tc) + + opt := &github.RepositoryListOptions{ + Type: "all", + ListOptions: github.ListOptions{PerPage: 100, Page: 0}, + } + + // get all pages of results + var allRepos []*github.Repository + for { + repos, resp, err := client.Repositories.List(context.Background(), args[0], opt) + + if err != nil { + return nil, err + } + allRepos = append(allRepos, repos...) + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + cloneUrls := []string{} + + for _, repo := range allRepos { + if os.Getenv("GHORG_CLONE_PROTOCOL") == "https" { + cloneUrls = append(cloneUrls, *repo.CloneURL) + } else { + cloneUrls = append(cloneUrls, *repo.SSHURL) + } + } + + return cloneUrls, nil +} diff --git a/cmd/clone_gitlab.go b/cmd/clone_gitlab.go new file mode 100644 index 0000000000..80c2762b6e --- /dev/null +++ b/cmd/clone_gitlab.go @@ -0,0 +1,23 @@ +package cmd + +import ( + "os" + + "github.com/gabrie30/ghorg/colorlog" +) + +func getGitLabOrgCloneUrls() ([]string, error) { + colorlog.PrintError("Gitlab org clone not available yet") + os.Exit(1) + // todo + cloneUrls := []string{} + return cloneUrls, nil +} + +func getGitLabUserCloneUrls() ([]string, error) { + colorlog.PrintError("Gitlab user clone not available yet") + os.Exit(1) + // todo + cloneUrls := []string{} + return cloneUrls, nil +} diff --git a/cmd/root.go b/cmd/root.go index eb81a88618..26a5a6fdf0 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,6 +4,7 @@ import ( "fmt" "os" + "github.com/gabrie30/ghorg/configs" "github.com/spf13/cobra" ) @@ -13,7 +14,7 @@ var rootCmd = &cobra.Command{ Short: "Ghorg is a fast way to clone multiple repos into a single directory", Long: `Ghorg is a fast way to clone multiple repos into a single directory`, Run: func(cmd *cobra.Command, args []string) { - // Do Stuff Here + configs.Load() }, } diff --git a/configs/configs.go b/configs/configs.go index b630bcd29e..4abb9ecbe7 100644 --- a/configs/configs.go +++ b/configs/configs.go @@ -38,6 +38,8 @@ func initConfig() { getOrSetDefaults("GHORG_ABSOLUTE_PATH_TO_CLONE_TO") getOrSetDefaults("GHORG_BRANCH") getOrSetDefaults("GHORG_CLONE_PROTOCOL") + getOrSetDefaults("GHORG_CLONE_TYPE") + getOrSetDefaults("GHORG_SCM_TYPE") } @@ -67,6 +69,10 @@ func getOrSetDefaults(envVar string) { os.Setenv(envVar, "master") case "GHORG_CLONE_PROTOCOL": os.Setenv(envVar, "https") + case "GHORG_CLONE_TYPE": + os.Setenv(envVar, "org") + case "GHORG_SCM_TYPE": + os.Setenv(envVar, "github") } } diff --git a/main.go b/main.go index 0b6c4892ff..d6b56a79cd 100644 --- a/main.go +++ b/main.go @@ -2,10 +2,8 @@ package main import ( "github.com/gabrie30/ghorg/cmd" - "github.com/gabrie30/ghorg/configs" ) func main() { - configs.Load() cmd.Execute() } diff --git a/sample-conf.yaml b/sample-conf.yaml index a353afdc48..42b648c6dd 100644 --- a/sample-conf.yaml +++ b/sample-conf.yaml @@ -12,3 +12,11 @@ GHORG_BRANCH: # How you'd like to clone the repos (https or ssh), defaults to https GHORG_CLONE_PROTOCOL: + +## Experimental + +# Clone a user or an org, defaults to org +GHORG_CLONE_TYPE: + +# Clone from github or gitlab, defaults to github +GHORG_SCM_TYPE: