func reverseAppsArticle(a *app.App, art interface{}, checked map[*app.App]bool) (string, error) { checked[a] = true var articles []*article.Article aa, _ := reusableapp.AppData(a).(*appData) if aa != nil { articles = aa.Articles } switch x := art.(type) { case string: for _, v := range articles { if articleId(v) == x { return a.Reverse(ArticleHandlerName, v.Slug()) } } case *article.Article: return a.Reverse(ArticleHandlerName, x.Slug()) case article.Article: return a.Reverse(ArticleHandlerName, x.Slug()) } if p := a.Parent(); p != nil && !checked[p] { return reverseAppsArticle(p, art, checked) } for _, v := range a.Included() { if checked[v] { continue } if url, err := reverseAppsArticle(v, art, checked); err == nil { return url, nil } } if id, ok := art.(string); ok { return "", fmt.Errorf("no article with id %q found", id) } return "", fmt.Errorf("can't reverse Article from %T, must be *Article or string (article id)", art) }
// New returns prepares the *app.App and then // returns a new Tester. It also disables // logging in the App, since the Tester does // its own logging. func New(r Reporter, a *app.App) *Tester { if !flag.Parsed() { flag.Parse() } if *remoteHost == "" { if gaeLocal != nil && *gaeLocal { h := gaeLocalHost remoteHost = &h } else if gaeRemote != nil && *gaeRemote { h := internal.AppEngineAppHost() if h == "" { panic(errors.New("no application found in app.yaml - please, specify one to run remote tests")) } remoteHost = &h } } if *remoteHost != "" { r.Log(fmt.Sprintf("using host %s", *remoteHost)) } if err := a.Prepare(); err != nil { r.Fatal(fmt.Errorf("error preparing app: %s", err)) } a.Logger = nil return &Tester{r, a} }
func loadDatabase(a *app.App, filename string) error { g, err := geoip.Open(filename) if err != nil { return err } a.Set(geoIPKey, g) return nil }
// AppDataWithKey works similarly to AppData, but uses the provided key instead. // Also, if the data is not found in the *app.App passed in as the first argument, // its children apps are also searched. This allows reusable apps to retrieve their // additional data in contexts where the reusable app pointer is not available. // (e.g. in template plugins which are called from the parent app). See gnd.la/apps/users // for an example of this usage. func AppDataWithKey(a *app.App, key interface{}) interface{} { ra, _ := a.Get(key).(*App) if ra != nil { return ra.Data() } if key != reusableAppKey { for _, ia := range a.Included() { if data := AppDataWithKey(ia, key); data != nil { return data } } } return nil }
func executeCommand(name string, cmd *command, args []string, a *app.App) (err error) { // Parse command flags set := flag.NewFlagSet(name, flag.ContinueOnError) set.Usage = func() { commandHelp(name, -1, os.Stderr) } flags := map[string]interface{}{} for _, arg := range cmd.opts.Flags { switch arg.typ { case typBool: var b bool set.BoolVar(&b, arg.name, arg.def.(bool), arg.help) flags[arg.name] = &b case typInt: var i int set.IntVar(&i, arg.name, arg.def.(int), arg.help) flags[arg.name] = &i case typString: var s string set.StringVar(&s, arg.name, arg.def.(string), arg.help) flags[arg.name] = &s default: panic("invalid arg type") } } // Print error/help messages ourselves set.SetOutput(ioutil.Discard) err = set.Parse(args) if err != nil { if err == flag.ErrHelp { return } if strings.Contains(err.Error(), "provided but not defined") { flagName := strings.TrimSpace(strings.Split(err.Error(), ":")[1]) fmt.Fprintf(os.Stderr, "command %s does not accept flag %s\n", name, flagName) return } return err } var params []string paramValues := make(map[string]string) for _, arg := range cmd.opts.Flags { params = append(params, arg.name) paramValues[arg.name] = fmt.Sprintf("%v", reflect.ValueOf(flags[arg.name]).Elem().Interface()) } provider := &contextProvider{ args: set.Args(), params: params, paramValues: paramValues, } if os.Getenv("GONDOLA_COMMANDS_NO_RECOVER") == "" { defer func() { if r := recover(); r != nil { if e, ok := r.(error); ok { err = e } else { err = fmt.Errorf("%v", r) } if file, line, ok := runtimeutil.PanicLocation(); ok { err = fmt.Errorf("%v (at %s:%d)", err, file, line) } } }() } ctx := a.NewContext(provider) defer a.CloseContext(ctx) cmd.handler(ctx) return }
// Attach attaches a reusable app into its parent app. func (a *App) Attach(parent *app.App) { parent.Include(a.Prefix, a.name, &a.App, a.ContainerTemplateName) }
func (b *Broadcaster) Attach(a *app.App) { a.HandleWebsocket(b.pattern(), b.handler()) a.AddTemplateVars(devserver.TemplateVars(&app.Context{})) a.AddTemplatePlugin(devserver.ReloadPlugin()) b.ts = time.Now() }
func (a *App) Attach(parent *app.App) { parent.SetUserFunc(userFunc) a.App.Attach(parent) }