Skip to content

Commit

Permalink
Spread implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
vmaggioli committed Jan 15, 2020
1 parent 1f4e043 commit 6c77e73
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 35 deletions.
10 changes: 8 additions & 2 deletions src/sprout/cli/cmdParser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"os"
"strings"

"github.com/Fair2Dare/sprout/src/sprout/model"
"github.com/docopt/docopt-go"
Expand All @@ -19,7 +20,7 @@ type SproutOptions struct {
}

const usage = `usage:
sprout [options] <command> [<args...>]
sprout [options] <command> [<args>...]
Options:
-h --help show this screen
Expand Down Expand Up @@ -54,7 +55,12 @@ func RunCommand(config *model.Config, options SproutOptions) {
}
switch options.Command {
case "spread":
SpreadCommand()
var command string
for _, arg := range options.Args {
command += arg + " "
}
command = strings.TrimSpace(command)
SpreadCommand(command)
case "create":
CreateCommand(config)
default:
Expand Down
55 changes: 32 additions & 23 deletions src/sprout/cli/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

"github.com/AlecAivazis/survey/v2"
"github.com/Fair2Dare/sprout/src/sprout/model"
Expand All @@ -15,7 +17,7 @@ import (
// CreateCommand opens a prompt to select which repositories to clone
func CreateCommand(config *model.Config) {
currDir, _ := os.Getwd()
if utils.FileExists(fmt.Sprintf("%s/%s", currDir, ".sprout_root.yml")) {
if utils.FileExists(fmt.Sprintf("%s%s%s", currDir, utils.PathSeparator, model.SproutRootFileName)) {
golog.Error("Sprouted project already exsists, please run \"sprout slash\" to remove project and start a new one")
return
}
Expand All @@ -26,28 +28,42 @@ func CreateCommand(config *model.Config) {
Options: options,
}
survey.AskOne(prompt, &selected)
createStructure(config.Projects, config.Repos, selected, true)
file, err := os.Create(model.SproutRootFileName)
if err != nil {
golog.Fatal(err)
}
root := &model.SproutRoot{Repos: []model.RepoWithPath{}}
createStructure(config.Projects, config.Repos, selected, root)
text, err := yaml.Marshal(root)
if err != nil {
golog.Fatal(err)
}
file.Write(text)
defer file.Close()
}

func createStructure(projects []model.Project, repos []model.Repo, reposToClone []string, isRoot bool) {
branch := model.SproutBranch{Folders: []string{}, Repos: []string{}}
func createStructure(projects []model.Project, repos []model.Repo, reposToClone []string, sproutRoot *model.SproutRoot) {
for _, project := range projects {
golog.Debugf("Creating directory for project \"%s\"", project.Name)
branch.Folders = append(branch.Folders, project.Name)
err := utils.Mkdir(project.Name)
if err != nil {
golog.Error(err)
continue
}
os.Chdir(project.Name)
createStructure(project.Projects, project.Repos, reposToClone, false)
createStructure(project.Projects, project.Repos, reposToClone, sproutRoot)
os.Chdir("..")
}

for _, repo := range repos {
if !utils.Contains(reposToClone, repo.Name) {
continue
}
currPath, _ := os.Getwd()
absCurrPath, _ := filepath.Abs(currPath)
urlRepoName := getRepoNameFromUrl(repo.URL)
newRepo := model.RepoWithPath{Name: urlRepoName, Path: fmt.Sprintf("%s%s%s", absCurrPath, utils.PathSeparator, urlRepoName)}
sproutRoot.Repos = append(sproutRoot.Repos, newRepo)
golog.Debugf("Cloning %s", repo.Name)
cmd := exec.Command("git", "clone", repo.URL)
cmd.Stdout = os.Stdout
Expand All @@ -56,24 +72,17 @@ func createStructure(projects []model.Project, repos []model.Repo, reposToClone
golog.Error(err)
}
}
}

golog.Debug("Generating branch file")
yamlFile, err := yaml.Marshal(&branch)
if err != nil {
golog.Fatal(err)
}
var file *os.File

if isRoot {
file, err = os.Create(".sprout_root.yml")
} else {
file, err = os.Create(".sprout_branch.yml")
func getRepoNameFromUrl(url string) string {
gitIndex := strings.Index(url, ".git")
if gitIndex == -1 {
return ""
}

if err != nil {
golog.Fatal(err)
lastSlashIndex := strings.LastIndex(url, "/")
if lastSlashIndex == -1 {
return ""
}
file.Write(yamlFile)
defer file.Close()

runes := []rune(url)
return string(runes[lastSlashIndex+1 : gitIndex])
}
38 changes: 31 additions & 7 deletions src/sprout/cli/spread.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,46 @@
package cli

import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"

"github.com/Fair2Dare/sprout/src/sprout/model"
"github.com/Fair2Dare/sprout/src/sprout/utils"
"github.com/kataras/golog"
"gopkg.in/yaml.v2"
)

// SpreadCommand executes the provided command across all cloned repositories
func SpreadCommand() {
func SpreadCommand(command string) {
golog.Info("Spreading \"%s\"", command)
splitCommand := strings.Fields(command)
currDir, _ := os.Getwd()
if !utils.FileExists(fmt.Sprintf("%s/%s", currDir, ".sprout_root.yml")) {
golog.Error("No sprouted project exists in current directory")
sproutRootPath := currDir + utils.PathSeparator + ".sprout_root.yml"
if !utils.FileExists(sproutRootPath) {
golog.Error("No sprouted project root exists in current directory")
return
}
if utils.FileExists(fmt.Sprintf("%s/%s", currDir, ".sprout_branch.yml")) {
golog.Error("Please execute spread commands in project root")
return

sproutRoot := model.SproutRoot{Repos: []model.RepoWithPath{}}
file, err := ioutil.ReadFile(sproutRootPath)
if err != nil {
golog.Fatal(err)
}
err = yaml.Unmarshal(file, &sproutRoot)
if err != nil {
golog.Fatal(err)
}
for _, repo := range sproutRoot.Repos {
golog.Infof("Inside \"%s\"", repo.Name)
cmd := exec.Command(splitCommand[0], splitCommand[1:]...)
cmd.Dir = repo.Path
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
golog.Error(err)
}
}
}
10 changes: 7 additions & 3 deletions src/sprout/model/config.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package model

// SproutRootFileName sets the file name that sprout generates when creating the directory structure
const SproutRootFileName string = ".sprout_root.yml"

// Config represents the layout of the sprout_config.yml file and all available flag options
type Config struct {
Verbose bool `yaml:"verbose"`
Projects []Project `yaml:"projects"`
Repos []Repo `yaml:"repos"`
}

type SproutBranch struct {
Folders []string `yaml:"folders"`
Repos []string `yaml:"repos"`
// SproutRoot represents the structure of o
type SproutRoot struct {
Repos []RepoWithPath `yaml:"repos"`
}

// GetAllRepos retrieves the names of all repositories in the specified Config struct
func (config *Config) GetAllRepos() (repos []string) {
options := []string{}
for _, repo := range config.Repos {
Expand Down
6 changes: 6 additions & 0 deletions src/sprout/model/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ type Repo struct {
Name string `yaml:"name"`
URL string `yaml:"url"`
}

// RepoWithPath is used to write to our hidden .sprout_root.yml file when generating the project layout
type RepoWithPath struct {
Name string `yaml:"name"`
Path string `yaml:"path"`
}

0 comments on commit 6c77e73

Please sign in to comment.