func (j *jsSDKCmd) setVersion(e *parsecli.Env, c *parsecli.Context) error { allVersions, err := j.getAllJSSdks(e) if err != nil { return err } valid := false for _, version := range allVersions { if version == j.newVersion { valid = true } } if !valid { return stackerr.New("Invalid SDK version selected.") } conf, err := parsecli.ConfigFromDir(e.Root) if err != nil { return err } conf.GetProjectConfig().Parse.JSSDK = j.newVersion if err := parsecli.StoreProjectConfig(e, conf); err != nil { return err } fmt.Fprintf(e.Out, "Current JavaScript SDK version is %s\n", conf.GetProjectConfig().Parse.JSSDK) return nil }
func (m *migrateCmd) run(e *parsecli.Env) error { c, err := parsecli.ConfigFromDir(e.Root) if err != nil { return err } c, err = m.upgradeLegacy(e, c) if err != nil { return err } localErr := parsecli.StoreConfig(e, c) projectErr := parsecli.StoreProjectConfig(e, c) if localErr == nil && projectErr == nil { legacy := filepath.Join(e.Root, parsecli.LegacyConfigFile) err := os.Remove(legacy) if err != nil { fmt.Fprintf(e.Err, "Could not delete: %q. Please remove this file manually.\n", legacy) } } else { local := filepath.Join(e.Root, parsecli.ParseLocal) err := os.Remove(local) if err != nil { fmt.Fprintf(e.Err, "Failed to clean up: %q. Please remove this file manually.\n", local) } project := filepath.Join(e.Root, parsecli.ParseProject) err = os.Remove(project) if err != nil { fmt.Fprintf(e.Err, "Failed to clean up: %q. Please remove this file manually.\n", project) } } fmt.Fprintln(e.Out, "Successfully migrated to the preferred config format.") return nil }
func (d *defaultCmd) run(e *parsecli.Env, args []string) error { var newDefault string if len(args) > 1 { return stackerr.Newf("unexpected arguments, only an optional app name is expected: %v", args) } if len(args) == 1 { newDefault = args[0] } config, err := parsecli.ConfigFromDir(e.Root) if err != nil { return err } if config.GetNumApps() == 0 { return stackerr.New("No apps are associated with this project. You can add some with parse add") } defaultApp := config.GetDefaultApp() switch newDefault { case "": return parsecli.PrintDefault(e, defaultApp) default: return parsecli.SetDefault(e, newDefault, defaultApp, config) } }
func AddSelectedParseApp( appName string, appConfig *parsecli.ParseAppConfig, args []string, makeDefault, verbose bool, e *parsecli.Env, ) error { config, err := parsecli.ConfigFromDir(e.Root) if err != nil { return err } parseConfig, ok := config.(*parsecli.ParseConfig) if !ok { return stackerr.New("Invalid Cloud Code config.") } // add app to config if _, ok := parseConfig.Applications[appName]; ok { return stackerr.Newf("App %s has already been added", appName) } parseConfig.Applications[appName] = appConfig if len(args) > 0 && args[0] != "" { alias := args[0] aliasConfig, ok := parseConfig.Applications[alias] if !ok { parseConfig.Applications[alias] = &parsecli.ParseAppConfig{Link: appName} } if ok && aliasConfig.GetLink() != "" { fmt.Fprintf(e.Out, "Overwriting alias: %q to point to %q\n", alias, appName) parseConfig.Applications[alias] = &parsecli.ParseAppConfig{Link: appName} } } if makeDefault { if _, ok := parseConfig.Applications[parsecli.DefaultKey]; ok { return stackerr.New(`Default key already set. To override default, use command "parse default"`) } parseConfig.Applications[parsecli.DefaultKey] = &parsecli.ParseAppConfig{Link: appName} } if err := parsecli.StoreConfig(e, parseConfig); err != nil { return err } if verbose { fmt.Fprintf(e.Out, "Written config for %q\n", appName) if makeDefault { fmt.Fprintf(e.Out, "Set %q as default\n", appName) } } return nil }
func (l *listCmd) printListOfApps(e *parsecli.Env) error { config, err := parsecli.ConfigFromDir(e.Root) if err != nil { if os.IsNotExist(err) { // print nothing if we are not in a parse app directory return nil } return stackerr.Wrap(err) } config.PrettyPrintApps(e) fmt.Fprintln(e.Out, "") return nil }
func newJsSdkHarnessWithConfig(t testing.TB) (*parsecli.Harness, *parsecli.Context) { h := newJsSdkHarness(t) h.MakeEmptyRoot() ensure.Nil(t, parsecli.CloneSampleCloudCode(h.Env, true)) h.Out.Reset() c, err := parsecli.ConfigFromDir(h.Env.Root) ensure.Nil(t, err) config, ok := (c).(*parsecli.ParseConfig) ensure.True(t, ok) return h, &parsecli.Context{Config: config} }
func (d *developCmd) contDeploy(e *parsecli.Env, deployer deployFunc, first, done chan struct{}) { if d.deployInterval == 0 { d.deployInterval = time.Second } var prevDeplInfo *deployInfo ticker := e.Clock.Ticker(d.deployInterval) defer ticker.Stop() latestError := false for { select { case <-ticker.C: case <-done: return } config, err := parsecli.ConfigFromDir(e.Root) if err != nil { if !latestError { latestError = true } if latestError { fmt.Fprintf( e.Err, `Config malformed. Please fix your config file in %s and try again. `, parsecli.GetConfigFile(e), ) } if first != nil { // first deploy aborted close(first) first = nil } continue } latestError = false newDeplInfo, _ := deployer(config.GetProjectConfig().Parse.JSSDK, prevDeplInfo, true, e) if !d.mustFetch { prevDeplInfo = newDeplInfo } if first != nil { // first deploy finished close(first) first = nil } } }
// useLatestJSSDK is a utility method used by deploy & develop // to write set jssdk version to latest available, if none set func UseLatestJSSDK(e *parsecli.Env) error { var j jsSDKCmd versions, err := j.getAllJSSdks(e) if err != nil { return err } if len(versions) == 0 { return stackerr.New("No JavaScript SDK version is available.") } config, err := parsecli.ConfigFromDir(e.Root) if err != nil { return err } config.GetProjectConfig().Parse.JSSDK = versions[0] return parsecli.StoreProjectConfig(e, config) }
func newDefaultParseConfig(t testing.TB, h *parsecli.Harness) *parsecli.ParseConfig { c, err := parsecli.ConfigFromDir(h.Env.Root) ensure.Nil(t, err) config, ok := c.(*parsecli.ParseConfig) ensure.True(t, ok) config.Applications = map[string]*parsecli.ParseAppConfig{ "first": {}, "second": {}, parsecli.DefaultKey: {Link: "first"}, } config.ProjectConfig = &parsecli.ProjectConfig{ Type: parsecli.LegacyParseFormat, Parse: &parsecli.ParseProjectConfig{}, } ensure.Nil(t, parsecli.StoreConfig(h.Env, config)) return config }
// NOTE: testing for legacy config format func newLegacyJsSdkHarnessWithConfig(t testing.TB) (*parsecli.Harness, *parsecli.Context) { h := newJsSdkHarness(t) h.MakeEmptyRoot() ensure.Nil(t, os.Mkdir(filepath.Join(h.Env.Root, parsecli.ConfigDir), 0755)) path := filepath.Join(h.Env.Root, parsecli.LegacyConfigFile) ensure.Nil(t, ioutil.WriteFile(path, []byte(`{ "global": { "parseVersion" : "1.2.9" } }`), 0600)) c, err := parsecli.ConfigFromDir(h.Env.Root) ensure.Nil(t, err) config, ok := (c).(*parsecli.ParseConfig) ensure.True(t, ok) return h, &parsecli.Context{Config: config} }
func TestDeployFilesNoVersion(t *testing.T) { t.Parallel() info := &deployInfo{ ReleaseName: "v1", ParseVersion: "latest", Checksums: deployFileData{ Cloud: map[string]string{"main.js": "d41d8cd98f00b204e9800998ecf8427e"}, Public: map[string]string{"index.html": "d41d8cd98f00b204e9800998ecf8427e"}, }, Versions: deployFileData{ Cloud: map[string]string{"main.js": "f1"}, Public: map[string]string{"index.html": "f1"}, }, } h := setupForDeploy(t, info) defer h.Stop() d := deployCmd{Verbose: true} res, err := d.deploy("", nil, false, h.Env) ensure.Nil(t, err) expected := &deployInfo{ ParseVersion: "latest", Checksums: deployFileData{ Cloud: map[string]string{"main.js": "4ece160cc8e5e828ee718e7367cf5d37"}, Public: map[string]string{"index.html": "9e2354a0ebac5852bc674026137c8612"}, }, Versions: deployFileData{ Cloud: map[string]string{"main.js": "f2"}, Public: map[string]string{"index.html": "f2"}, }, } ensure.DeepEqual(t, res, expected) ensure.DeepEqual(t, h.Out.String(), fmt.Sprintf(`Uploading source files Uploading recent changes to scripts... The following files will be uploaded: %s The following files will be ignored: %s Uploading recent changes to hosting... The following files will be uploaded: %s The following files will be ignored: %s Finished uploading files New release is named v1 (using Parse JavaScript SDK vlatest) `, filepath.Join(h.Env.Root, parsecli.CloudDir, "main.js"), strings.Join([]string{ filepath.Join(h.Env.Root, parsecli.CloudDir, "sample.txt"), filepath.Join(h.Env.Root, parsecli.CloudDir, "test~")}, "\n"), filepath.Join(h.Env.Root, parsecli.HostingDir, "index.html"), strings.Join([]string{ filepath.Join(h.Env.Root, parsecli.HostingDir, "#ignore"), filepath.Join(h.Env.Root, parsecli.HostingDir, ".ignore")}, "\n"), ), ) c, err := parsecli.ConfigFromDir(h.Env.Root) ensure.Nil(t, err) config, ok := (c).(*parsecli.ParseConfig) ensure.True(t, ok) ensure.DeepEqual(t, config.ProjectConfig.Parse.JSSDK, "2.0") ensure.True(t, strings.Contains(h.Err.String(), `JS SDK version not set, setting it to latest available JS SDK version `), ) }
func main() { // some parts of apps.go are unable to handle // interrupts, this logic ensures we exit on system interrupts interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) go func() { <-interrupt os.Exit(1) }() e := parsecli.Env{ Root: os.Getenv("PARSE_ROOT"), Server: os.Getenv("PARSE_SERVER"), ErrorStack: os.Getenv("PARSE_ERROR_STACK") == "1", ParserEmail: os.Getenv("PARSER_EMAIL"), Out: os.Stdout, Err: os.Stderr, In: os.Stdin, Exit: os.Exit, Clock: clock.New(), } if e.Root == "" { cur, err := os.Getwd() if err != nil { fmt.Fprintf(e.Err, "Failed to get current directory:\n%s\n", err) os.Exit(1) } root := parsecli.GetProjectRoot(&e, cur) if parsecli.IsProjectDir(root) { e.Root = root config, err := parsecli.ConfigFromDir(root) if err != nil { fmt.Fprintln(e.Err, err) os.Exit(1) } e.Type = config.GetProjectConfig().Type if e.ParserEmail == "" { e.ParserEmail = config.GetProjectConfig().ParserEmail } } else { e.Type = parsecli.LegacyParseFormat e.Root = parsecli.GetLegacyProjectRoot(&e, cur) } } if e.Type != parsecli.LegacyParseFormat && e.Type != parsecli.ParseFormat && e.Type != parsecli.HerokuFormat { fmt.Fprintf(e.Err, "Unknown project type %d.\n", e.Type) os.Exit(1) } if e.Server == "" { e.Server = parsecli.DefaultBaseURL } apiClient, err := parsecli.NewParseAPIClient(&e) if err != nil { fmt.Fprintln(e.Err, err) os.Exit(1) } e.ParseAPIClient = apiClient if e.Type == parsecli.HerokuFormat { apiClient, err := parsecli.NewHerokuAPIClient(&e) if err != nil { fmt.Fprintln(e.Err, err) os.Exit(1) } e.HerokuAPIClient = apiClient } var ( rootCmd *cobra.Command command []string ) switch e.Type { case parsecli.LegacyParseFormat, parsecli.ParseFormat: command, rootCmd = parseRootCmd(&e) case parsecli.HerokuFormat: command, rootCmd = herokuRootCmd(&e) } if len(command) == 0 || command[0] != "update" { message, err := checkIfSupported(&e, parsecli.Version, command...) if err != nil { fmt.Fprintln(e.Err, err) os.Exit(1) } if message != "" { fmt.Fprintln(e.Err, message) } } if err := rootCmd.Execute(); err != nil { // Error is already printed in Execute() os.Exit(1) } }
func (c *configureCmd) projectType(e *parsecli.Env, args []string) error { config, err := parsecli.ConfigFromDir(e.Root) if err != nil { return err } if len(args) > 1 { return stackerr.Newf("Invalid args: %v, only an optional project type argument is expected.", args) } validTypes := map[string]int{"parse": parsecli.ParseFormat} invertedTypes := map[int]string{parsecli.ParseFormat: "parse"} numKeys := len(validTypes) var validKeys []string for key := range validTypes { validKeys = append(validKeys, key) } sort.Strings(validKeys) var selectionString string for n, key := range validKeys { selectionString += fmt.Sprintf("%d: %s\n", 1+n, key) } selectedProjectType := -1 if len(args) != 0 { projectType, ok := validTypes[args[0]] if !ok { return stackerr.Newf("Invalid projectType: %v, valid types are: \n%s", selectionString) } selectedProjectType = projectType } for i := 0; i < 3; i++ { fmt.Fprintf(e.Out, `Select from the listed project types: %s Enter a number between 1 and %d: `, selectionString, numKeys, ) var selection string fmt.Fscanf(e.In, "%s\n", &selection) num, err := strconv.Atoi(selection) if err != nil || num < 1 || num > numKeys { fmt.Fprintf(e.Err, "Invalid selection. Please enter a number between 1 and %d\n", numKeys) continue } projectType, ok := validTypes[validKeys[num-1]] if !ok { return stackerr.Newf("Invalid projectType: %v, valid types are: \n%s", selectionString) } selectedProjectType = projectType break } if selectedProjectType == -1 { return stackerr.Newf("Could not make a selection. Please try again.") } config.GetProjectConfig().Type = selectedProjectType if err := parsecli.StoreProjectConfig(e, config); err != nil { fmt.Fprintln(e.Err, "Could not save selected project type to project config") return err } fmt.Fprintf(e.Out, "Successfully set project type to: %v\n", invertedTypes[selectedProjectType]) return nil }