From dc61e75a16a654b2f87bd139c04fc8a7c2fb1cea Mon Sep 17 00:00:00 2001 From: Jonathan Seth Mainguy Date: Wed, 27 Oct 2021 12:08:44 -0400 Subject: [PATCH] refactor to multiple files --- files.go | 50 +++++++++++++ git.go | 138 ++++++++++++++++++++++++++++++++++ main.go | 210 +++++----------------------------------------------- template.go | 30 ++++++++ usage.go | 13 ++++ 5 files changed, 248 insertions(+), 193 deletions(-) create mode 100644 files.go create mode 100644 git.go create mode 100644 template.go create mode 100644 usage.go diff --git a/files.go b/files.go new file mode 100644 index 0000000..c02eb24 --- /dev/null +++ b/files.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +func copyFiles(src, dst string) { + srcFiles := getAllFiles(src) + for _, file := range srcFiles { + destFile := strings.TrimPrefix(file, src) + destFile = dst + "/" + destFile + bytesRead, err := ioutil.ReadFile(file) + if err != nil { + log.Fatal(err) + } + err = ioutil.WriteFile(destFile, bytesRead, 0644) + + if err != nil { + log.Fatal(err) + } + + } +} + +// https://golang.cafe/blog/how-to-list-files-in-a-directory-in-go.html +func getAllFiles(dirPath string) (files []string) { + err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { + if err != nil { + fmt.Println(err) + return err + } + + if !info.IsDir() { + // Don't list .git/ files + if !strings.Contains(path, ".git/") && !strings.Contains(path, ".template/") { + files = append(files, path) + } + } + return nil + }) + if err != nil { + fmt.Println(err) + } + return files +} diff --git a/git.go b/git.go new file mode 100644 index 0000000..d97fd1a --- /dev/null +++ b/git.go @@ -0,0 +1,138 @@ +package main + +import ( + "context" + "fmt" + "os" + "strconv" + "strings" + + git "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/config" + "github.com/go-git/go-git/v5/plumbing" + "github.com/google/go-github/v39/github" +) + +func pushBranch(newBranchName string, ctx context.Context, currentRepo *git.Repository) { + // Create Worktree + wt, err := currentRepo.Worktree() + if err != nil { + panic(err) + } + // Check worktree status + wtStatus, err := wt.Status() + if err != nil { + panic(err) + } + // If not clean, new branch, add, commit, push + if !wtStatus.IsClean() { + // Checkout new branch + err := wt.Checkout(&git.CheckoutOptions{ + Create: true, + Keep: true, + Force: false, + Branch: plumbing.NewBranchReferenceName(newBranchName), + }) + if err != nil { + panic(err) + } + // git add . + _, err = wt.Add(".") + if err != nil { + panic(err) + } + // git commit -m + _, err = wt.Commit("GGTH template updating", &git.CommitOptions{}) + if err != nil { + panic(err) + } + // git push origin + err = currentRepo.PushContext(ctx, &git.PushOptions{ + RemoteName: "origin", + }) + if err != nil { + panic(err) + } + + } + +} + +func getNewBranchName(branches []*github.Branch) string { + var pullRequestIncrement int + for _, branch := range branches { + if strings.HasPrefix(*branch.Name, "ggth-") { + incrementStr := strings.TrimPrefix(*branch.Name, "ggth-") + increment, err := strconv.Atoi(incrementStr) + if err != nil { + panic(err) + } + + if increment >= pullRequestIncrement { + pullRequestIncrement = increment + 1 + } + + } + } + newBranchName := fmt.Sprintf("ggth-%d", pullRequestIncrement) + return newBranchName +} + +func cloneRepo(repoDir string, templateRepo *github.Repository) { + if templateRepo != nil { + if _, err := os.Stat(repoDir); !os.IsNotExist(err) { + // Delete it, and clone it fresh + err = os.RemoveAll(repoDir) + if err != nil { + panic(err) + } + } + _, err := git.PlainClone(repoDir, false, &git.CloneOptions{ + URL: *templateRepo.CloneURL, + Progress: nil, + }) + if err != nil { + panic(err) + } + + } else { + fmt.Println("Templated repo could not be found") + os.Exit(1) + } +} + +func getRepoNameFromGitConfig(currentRepo *git.Repository) (owner, name string) { + currentRepoConfig, err := currentRepo.Config() + var originURL string + if err != nil { + panic(err) + } + for _, remote := range currentRepoConfig.Remotes { + if remote.Name == "origin" { + for _, URL := range remote.URLs { + originURL = URL + } + } + } + + // SSH style + repoName := strings.ReplaceAll(originURL, "git@github.com:", "") + repoName = strings.ReplaceAll(repoName, ".git", "") + // HTTPS style + repoName = strings.ReplaceAll(repoName, "https://github.com/", "") + ownerRepo := strings.Split(repoName, "/") + owner = strings.ToLower(ownerRepo[0]) + name = strings.ToLower(ownerRepo[1]) + + return owner, name +} + +func getGitProfile() (gitName, gitEmail string) { + gitConfig, err := config.LoadConfig(config.GlobalScope) + if err != nil { + panic(err) + } + gitName = gitConfig.User.Name + gitEmail = gitConfig.User.Email + return gitName, gitEmail +} diff --git a/main.go b/main.go index 80a1f04..5d2284b 100644 --- a/main.go +++ b/main.go @@ -2,124 +2,15 @@ package main import ( "context" - "fmt" - "io/ioutil" - "log" "os" - "path/filepath" - "strconv" - "strings" git "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/config" - "github.com/go-git/go-git/v5/plumbing" "github.com/google/go-github/v39/github" "golang.org/x/oauth2" ) -func getRepoNameFromGitConfig(currentRepo *git.Repository) string { - currentRepoConfig, err := currentRepo.Config() - var originURL string - if err != nil { - panic(err) - } - for _, remote := range currentRepoConfig.Remotes { - if remote.Name == "origin" { - for _, URL := range remote.URLs { - originURL = URL - } - } - } - - // SSH style - repoName := strings.ReplaceAll(originURL, "git@github.com:", "") - repoName = strings.ReplaceAll(repoName, ".git", "") - // HTTPS style - repoName = strings.ReplaceAll(repoName, "https://github.com/", "") - return repoName -} - -func getUsage() string { - usage, err := ioutil.ReadFile(".usage") - if err != nil { - panic(err) - } - return string(usage) -} - -func templateFile(filename string, repo *github.Repository, gitName, gitEmail string) { - usage := getUsage() - read, err := ioutil.ReadFile(filename) - if err != nil { - panic(err) - } - newContents := strings.Replace(string(read), "--REPOLINK--", *repo.HTMLURL, -1) - newContents = strings.Replace(newContents, "--DESCRIPTION--", *repo.Description, -1) - newContents = strings.Replace(newContents, "--BINARY--", *repo.Name, -1) - newContents = strings.Replace(newContents, "--REPONAME--", *repo.Name, -1) - newContents = strings.Replace(newContents, "--REPOOWNER--", *repo.Owner.Login, -1) - - newContents = strings.Replace(newContents, "--MAINTAINEREMAIL--", gitEmail, -1) - newContents = strings.Replace(newContents, "--MAINTAINERNAME--", gitName, -1) - newContents = strings.Replace(newContents, "--USAGE--", usage, -1) - - err = ioutil.WriteFile(filename, []byte(newContents), 0664) - if err != nil { - panic(err) - } -} - -// https://golang.cafe/blog/how-to-list-files-in-a-directory-in-go.html -func getAllFiles(dirPath string) (files []string) { - err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { - if err != nil { - fmt.Println(err) - return err - } - - if !info.IsDir() { - // Don't list .git/ files - if !strings.Contains(path, ".git/") && !strings.Contains(path, ".template/") { - files = append(files, path) - } - } - return nil - }) - if err != nil { - fmt.Println(err) - } - return files -} - -func getGitProfile() (gitName, gitEmail string) { - gitConfig, err := config.LoadConfig(config.GlobalScope) - if err != nil { - panic(err) - } - gitName = gitConfig.User.Name - gitEmail = gitConfig.User.Email - return gitName, gitEmail -} - -func copyFiles(src, dst string) { - srcFiles := getAllFiles(src) - for _, file := range srcFiles { - destFile := strings.TrimPrefix(file, src) - destFile = dst + "/" + destFile - bytesRead, err := ioutil.ReadFile(file) - if err != nil { - log.Fatal(err) - } - err = ioutil.WriteFile(destFile, bytesRead, 0644) - - if err != nil { - log.Fatal(err) - } - - } -} - func main() { + // Create github client ctx := context.Background() ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: os.Getenv("ghToken")}, @@ -128,107 +19,40 @@ func main() { client := github.NewClient(tc) - gitName, gitEmail := getGitProfile() + // Open repo on fs, to determine upstream gitHub information, and make changes currentRepo, err := git.PlainOpen(".") if err != nil { panic(err) } - repoURL := getRepoNameFromGitConfig(currentRepo) - ownerRepo := strings.Split(repoURL, "/") - owner := strings.ToLower(ownerRepo[0]) - repoName := strings.ToLower(ownerRepo[1]) + // Open Github Repository + owner, repoName := getRepoNameFromGitConfig(currentRepo) repo, _, err := client.Repositories.Get(ctx, owner, repoName) if err != nil { panic(err) } - repoDir := "/tmp/foo/" + // Retrieve templateRepo from currentRepo so we can clone it templateRepo := repo.GetTemplateRepository() - if templateRepo != nil { - fmt.Println(*templateRepo.Name) - fmt.Println(*templateRepo.CloneURL) - - if _, err := os.Stat(repoDir); !os.IsNotExist(err) { - // Delete it, and clone it fresh - err = os.RemoveAll(repoDir) - if err != nil { - panic(err) - } - } - _, err := git.PlainClone(repoDir, false, &git.CloneOptions{ - URL: *templateRepo.CloneURL, - Progress: nil, - }) - if err != nil { - panic(err) - } - - } - copyFiles(repoDir, ".") + // Clone template repo to a temporary directory + tempTemplateDir := "/tmp/foo/" + cloneRepo(tempTemplateDir, templateRepo) + // Copy files from template to current Repo + copyFiles(tempTemplateDir, ".") + // Template all files in current Repo files := getAllFiles(".") + // Get git username and email, used for template variables + gitName, gitEmail := getGitProfile() for _, file := range files { templateFile(file, repo, gitName, gitEmail) } - // What branch we on - branches, _, err := client.Repositories.ListBranches(ctx, owner, repoName, &github.BranchListOptions{}) - if err != nil { - panic(err) - } - - var pullRequestIncrement int - for _, branch := range branches { - if strings.HasPrefix(*branch.Name, "ggth-") { - incrementStr := strings.TrimPrefix(*branch.Name, "ggth-") - increment, err := strconv.Atoi(incrementStr) - if err != nil { - panic(err) - } - - if increment >= pullRequestIncrement { - pullRequestIncrement = increment + 1 - } - } - } - // Check worktree status - wt, err := currentRepo.Worktree() - if err != nil { - panic(err) - } - wtStatus, err := wt.Status() + // Create new branch for PR + branches, _, err := client.Repositories.ListBranches(ctx, owner, repoName, &github.BranchListOptions{}) if err != nil { panic(err) } + newBranchName := getNewBranchName(branches) // If not clean, checkout, add, commit, push - if !wtStatus.IsClean() { - newBranchName := fmt.Sprintf("ggth-%d", pullRequestIncrement) - err = wt.Checkout(&git.CheckoutOptions{ - Create: true, - Keep: true, - Force: false, - Branch: plumbing.NewBranchReferenceName(newBranchName), - }) - if err != nil { - panic(err) - } - - _, err = wt.Add(".") - if err != nil { - panic(err) - } - - _, err = wt.Commit("GGTH template updating", &git.CommitOptions{}) - if err != nil { - panic(err) - } - - err = currentRepo.PushContext(ctx, &git.PushOptions{ - RemoteName: "origin", - }) - if err != nil { - panic(err) - } - - } + pushBranch(newBranchName, ctx, currentRepo) } diff --git a/template.go b/template.go new file mode 100644 index 0000000..56398e9 --- /dev/null +++ b/template.go @@ -0,0 +1,30 @@ +package main + +import ( + "io/ioutil" + "strings" + + "github.com/google/go-github/v39/github" +) + +func templateFile(filename string, repo *github.Repository, gitName, gitEmail string) { + usage := getUsage() + read, err := ioutil.ReadFile(filename) + if err != nil { + panic(err) + } + newContents := strings.Replace(string(read), "--REPOLINK--", *repo.HTMLURL, -1) + newContents = strings.Replace(newContents, "--DESCRIPTION--", *repo.Description, -1) + newContents = strings.Replace(newContents, "--BINARY--", *repo.Name, -1) + newContents = strings.Replace(newContents, "--REPONAME--", *repo.Name, -1) + newContents = strings.Replace(newContents, "--REPOOWNER--", *repo.Owner.Login, -1) + + newContents = strings.Replace(newContents, "--MAINTAINEREMAIL--", gitEmail, -1) + newContents = strings.Replace(newContents, "--MAINTAINERNAME--", gitName, -1) + newContents = strings.Replace(newContents, "--USAGE--", usage, -1) + + err = ioutil.WriteFile(filename, []byte(newContents), 0664) + if err != nil { + panic(err) + } +} diff --git a/usage.go b/usage.go new file mode 100644 index 0000000..160d2b5 --- /dev/null +++ b/usage.go @@ -0,0 +1,13 @@ +package main + +import ( + "io/ioutil" +) + +func getUsage() string { + usage, err := ioutil.ReadFile(".usage") + if err != nil { + panic(err) + } + return string(usage) +}