package grm import ( "errors" "fmt" "gitlab.com/revalus/grm/internal/commands" "gitlab.com/revalus/grm/internal/config" "gitlab.com/revalus/grm/internal/echo" "io" "sync" ) const ( AppName = "Git repository manager" AppDescription = "Manage your repository with simple grm" VERSION = "0.3.2" errNotFoundTags = "no repository was found with the specified tags" errNotFoundName = "no repository was found with the specified name" ) type GitRepositoryManager struct { cliArguments config.CliArguments configuration config.Configuration } func (g *GitRepositoryManager) Parse(args []string) error { arguments, err := config.ParseCliArguments(AppName, AppDescription, args) if err != nil { fmt.Printf("Error: %v", err.Error()) return err } configFileContent, err := getFileContent(arguments.ConfigurationFile) if err != nil { fmt.Printf("Error: %v", err.Error()) return err } fileExtension, err := getFileExtension(arguments.ConfigurationFile) if err != nil { fmt.Printf("Error: %v", err.Error()) return err } configuration, err := config.GetRepositoryConfig(configFileContent, fileExtension) if err != nil { fmt.Printf("Error: %v", err.Error()) return err } g.cliArguments = arguments g.configuration = configuration return nil } func (g *GitRepositoryManager) Run(w io.Writer) int { echo.Color(g.cliArguments.Color) echo.Output(w) exitCode := 0 if len(g.cliArguments.LimitToTags) != 0 { err := g.limitRepositoriesToTags() if err != nil { echo.ErrorfMsg(err.Error()) return 1 } } if g.cliArguments.LimitToName != "" { err := g.limitRepositoryToName() if err != nil { echo.ErrorfMsg(err.Error()) return 1 } } if g.cliArguments.Sync && exitCode == 0 { echo.InfoFMsg("Synchronizing repositories") sync := commands.NewSynchronizer(g.configuration.Workspace) g.runCommand(sync) echo.InfoFMsg("All repositories are synced") } if g.cliArguments.Status && exitCode == 0 { echo.InfoFMsg("Current status of repositories") status := commands.NewStatusChecker(g.configuration.Workspace) g.runCommand(status) } if g.cliArguments.Version { echo.InfoFMsg("Current version: %v", VERSION) } return exitCode } func describeStatus(status commands.CommandStatus) { if status.Error { echo.RedMessageF("Repository \"%v\": an error occurred: %v", status.Name, status.Message) return } if status.Changed { echo.YellowMessageF("Repository \"%v\": %v", status.Name, status.Message) } else { echo.GreenMessageF("Repository \"%v\": %v", status.Name, status.Message) } } func (g *GitRepositoryManager) limitRepositoriesToTags() error { limitedTagsTmp := []config.RepositoryConfig{} for _, item := range g.configuration.Repositories { if checkAnyOfItemInSlice(item.Tags, g.cliArguments.LimitToTags) { limitedTagsTmp = append(limitedTagsTmp, item) } } if len(limitedTagsTmp) == 0 { return errors.New(errNotFoundTags) } g.configuration.Repositories = reverseRepositoryConfigs(limitedTagsTmp) return nil } func (g *GitRepositoryManager) limitRepositoryToName() error { for _, item := range g.configuration.Repositories { if g.cliArguments.LimitToName == item.Name { g.configuration.Repositories = []config.RepositoryConfig{item} return nil } } return errors.New(errNotFoundName) } func (g *GitRepositoryManager) runCommand(cmd commands.Command) { routines := make(chan struct{}, g.cliArguments.Routines) var wg sync.WaitGroup for _, repo := range g.configuration.Repositories { if repo.Skip && !g.cliArguments.IgnoreSkipped { continue } wg.Add(1) go func(r config.RepositoryConfig) { defer wg.Done() routines <- struct{}{} describeStatus(cmd.Command(r)) <-routines }(repo) } wg.Wait() }