func PrepareConfigurationMigration(dir string) (func() bool, func() error) { environmentLocation := filepath.Join(dir, "config.yml") env, err := loadOrInitializeEnvironment(environmentLocation) if err != nil { themekit.NotifyError(err) return func() bool { return false }, func() error { return err } } confirmationFn := func() bool { before, _ := ioutil.ReadFile(environmentLocation) after := env.String() fmt.Println(themekit.YellowText("Compare changes to configuration:")) fmt.Println(themekit.YellowText("Before:\n"), themekit.GreenText(string(before))) fmt.Println(themekit.YellowText("After:\n"), themekit.RedText(after)) reader := bufio.NewReader(os.Stdin) fmt.Println(themekit.YellowText("Does this look correct? (y/n)")) text, _ := reader.ReadString('\n') return strings.TrimSpace(text) == "y" } saveFn := func() error { return env.Save(environmentLocation) } return confirmationFn, saveFn }
func extractEventLog(el *chan themekit.ThemeEvent, args map[string]interface{}) { var ok bool if *el, ok = args["eventLog"].(chan themekit.ThemeEvent); !ok { themekit.NotifyError(errors.New("eventLog is not of a valid type")) } }
func doBootstrap(options BootstrapOptions) chan bool { pwd, _ := os.Getwd() if pwd != options.Directory { os.Chdir(options.Directory) } zipLocation, err := zipPathForVersion(options.Version) if err != nil { themekit.NotifyError(err) done := make(chan bool) close(done) return done } name := "Timber-" + options.Version if len(options.Prefix) > 0 { name = options.Prefix + "-" + name } clientForNewTheme, themeEvents := options.Client.CreateTheme(name, zipLocation) mergeEvents(options.getEventLog(), []chan themekit.ThemeEvent{themeEvents}) if options.SetThemeId { AddConfiguration(options.Directory, options.Environment, clientForNewTheme.GetConfiguration()) } os.Chdir(pwd) downloadOptions := DownloadOptions{} downloadOptions.Client = clientForNewTheme downloadOptions.EventLog = options.getEventLog() done := Download(downloadOptions) return done }
func constructFileWatcher(dir string, config themekit.Configuration) chan themekit.AssetEvent { filter := themekit.NewEventFilterFromPatternsAndFiles(config.IgnoredFiles, config.Ignores) watcher, err := themekit.NewFileWatcher(dir, true, filter) if err != nil { themekit.NotifyError(err) } return watcher }
func extractStringSlice(key string, args map[string]interface{}) []string { var ok bool var strs []string if strs, ok = args[key].([]string); !ok { errMsg := fmt.Sprintf("%s is not of valid type", key) themekit.NotifyError(errors.New(errMsg)) } return strs }
func drainErrors(errs chan error) { for { if err := <-errs; err != nil { themekit.NotifyError(err) } else { break } } }
func extractThemeClient(t *themekit.ThemeClient, args map[string]interface{}) { var ok bool if args["themeClient"] == nil { return } if *t, ok = args["themeClient"].(themekit.ThemeClient); !ok { themekit.NotifyError(errors.New("themeClient is not of a valid type")) } }
func AddConfiguration(dir, environment string, config themekit.Configuration) { environmentLocation := filepath.Join(dir, "config.yml") env, err := loadOrInitializeEnvironment(environmentLocation) env.SetConfiguration(environment, config) err = env.Save(environmentLocation) if err != nil { themekit.NotifyError(err) } }
func extractBool(s *bool, key string, args map[string]interface{}) { var ok bool if args[key] == nil { return } if *s, ok = args[key].(bool); !ok { errMsg := fmt.Sprintf("%s is not of valid type", key) themekit.NotifyError(errors.New(errMsg)) } }
func toClientAndFilesAsync(args map[string]interface{}, fn func(themekit.ThemeClient, []string) chan bool) chan bool { var ok bool var themeClient themekit.ThemeClient var filenames []string extractThemeClient(&themeClient, args) if filenames, ok = args["filenames"].([]string); !ok { themekit.NotifyError(errors.New("filenames are not of valid type")) } return fn(themeClient, filenames) }
func MigrateConfiguration(dir string) error { environmentLocation := filepath.Join(dir, "config.yml") env, err := loadOrInitializeEnvironment(environmentLocation) if err != nil { themekit.NotifyError(err) return err } err = env.Save(environmentLocation) return err }
func readAndPrepareFiles(filenames []string, results chan themekit.AssetEvent) { for _, filename := range filenames { asset, err := loadAsset(filename) if err == nil { results <- themekit.NewUploadEvent(asset) } else if err.Error() != "File is a directory" { themekit.NotifyError(err) } } close(results) }
func writeToDisk(asset themekit.Asset, eventLog chan themekit.ThemeEvent) { dir, err := os.Getwd() if err != nil { themekit.NotifyError(err) return } perms, err := os.Stat(dir) if err != nil { themekit.NotifyError(err) return } filename := fmt.Sprintf("%s/%s", dir, asset.Key) err = os.MkdirAll(filepath.Dir(filename), perms.Mode()) if err != nil { themekit.NotifyError(err) return } file, err := os.Create(filename) if err != nil { themekit.NotifyError(err) return } defer file.Sync() defer file.Close() var data []byte switch { case len(asset.Value) > 0: data = []byte(asset.Value) case len(asset.Attachment) > 0: data, err = base64.StdEncoding.DecodeString(asset.Attachment) if err != nil { themekit.NotifyError(errors.New(fmt.Sprintf("Could not decode %s. error: %s", asset.Key, err))) return } } if len(data) > 0 { _, err = file.Write(data) } if err != nil { themekit.NotifyError(err) } else { event := basicEvent{ Title: "FS Event", EventType: "Write", Target: filename, etype: "fsevent", Formatter: func(b basicEvent) string { return themekit.GreenText(fmt.Sprintf("Successfully wrote %s to disk", b.Target)) }, } logEvent(event, eventLog) } }
func extractThemeClients(args map[string]interface{}) []themekit.ThemeClient { if args["environments"] == nil { return []themekit.ThemeClient{} } var ok bool var environments themekit.Environments if environments, ok = args["environments"].(themekit.Environments); !ok { themekit.NotifyError(errors.New("environments is not of a valid type")) } clients := make([]themekit.ThemeClient, len(environments), len(environments)) idx := 0 for _, configuration := range environments { clients[idx] = themekit.NewThemeClient(configuration) idx++ } return clients }
func ConfigureCommand(args map[string]interface{}) chan bool { options := defaultOptions() extractString(&options.Environment, "environment", args) extractString(&options.Directory, "directory", args) extractString(&options.Domain, "domain", args) extractString(&options.AccessToken, "access_token", args) extractInt(&options.BucketSize, "bucket_size", args) extractInt(&options.RefillRate, "refill_rate", args) extractEventLog(&options.EventLog, args) if options.areInvalid() { themekit.NotifyError(options.configurationErrors()) } Configure(options) done := make(chan bool) close(done) return done }