コード例 #1
0
ファイル: template.go プロジェクト: rainycape/gondola
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)
}
コード例 #2
0
ファイル: tester.go プロジェクト: rainycape/gondola
// 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}
}
コード例 #3
0
ファイル: geoip_std.go プロジェクト: rainycape/gondola
func loadDatabase(a *app.App, filename string) error {
	g, err := geoip.Open(filename)
	if err != nil {
		return err
	}
	a.Set(geoIPKey, g)
	return nil
}
コード例 #4
0
ファイル: app.go プロジェクト: rainycape/gondola
// 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
}
コード例 #5
0
ファイル: commands.go プロジェクト: rainycape/gondola
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
}
コード例 #6
0
ファイル: app.go プロジェクト: rainycape/gondola
// 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)
}
コード例 #7
0
ファイル: devutil.go プロジェクト: rainycape/gondola
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()
}
コード例 #8
0
ファイル: app.go プロジェクト: rainycape/gondola
func (a *App) Attach(parent *app.App) {
	parent.SetUserFunc(userFunc)
	a.App.Attach(parent)
}