<commit_before>package cli

import (
	"errors"
	"flag"
	"strconv"
	"strings"
	"time"
)

// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
	App       *App
	Command   Command
	flagSet   *flag.FlagSet
	globalSet *flag.FlagSet
	setFlags  map[string]bool
}

// Creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
	return &Context{App: app, flagSet: set, globalSet: globalSet}
}

// Looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Int(name string) int {
	return lookupInt(name, c.flagSet)
}

// Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) Duration(name string) time.Duration {
	return lookupDuration(name, c.flagSet)
}

// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
func (c *Context) Float64(name string) float64 {
	return lookupFloat64(name, c.flagSet)
}

// Looks up the value of a local bool flag, returns false if no bool flag exists
func (c *Context) Bool(name string) bool {
	return lookupBool(name, c.flagSet)
}

// Looks up the value of a local boolT flag, returns false if no bool flag exists
func (c *Context) BoolT(name string) bool {
	return lookupBoolT(name, c.flagSet)
}

// Looks up the value of a local string flag, returns "" if no string flag exists
func (c *Context) String(name string) string {
	return lookupString(name, c.flagSet)
}

// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
func (c *Context) StringSlice(name string) []string {
	return lookupStringSlice(name, c.flagSet)
}

// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
func (c *Context) IntSlice(name string) []int {
	return lookupIntSlice(name, c.flagSet)
}

// Looks up the value of a local generic flag, returns nil if no generic flag exists
func (c *Context) Generic(name string) interface{} {
	return lookupGeneric(name, c.flagSet)
}

// Looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int {
	return lookupInt(name, c.globalSet)
}

// Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) GlobalDuration(name string) time.Duration {
	return lookupDuration(name, c.globalSet)
}

// Looks up the value of a global bool flag, returns false if no bool flag exists
func (c *Context) GlobalBool(name string) bool {
	return lookupBool(name, c.globalSet)
}

// Looks up the value of a global string flag, returns "" if no string flag exists
func (c *Context) GlobalString(name string) string {
	return lookupString(name, c.globalSet)
}

// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string {
	return lookupStringSlice(name, c.globalSet)
}

// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int {
	return lookupIntSlice(name, c.globalSet)
}

// Looks up the value of a global generic flag, returns nil if no generic flag exists
func (c *Context) GlobalGeneric(name string) interface{} {
	return lookupGeneric(name, c.globalSet)
}

// Determines if the flag was actually set exists
func (c *Context) IsSet(name string) bool {
	if c.setFlags == nil {
		c.setFlags = make(map[string]bool)
		c.flagSet.Visit(func(f *flag.Flag) {
			c.setFlags[f.Name] = true
		})
	}
	return c.setFlags[name] == true
}

// Returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) {
	for _, flag := range c.Command.Flags {
		name := strings.Split(flag.getName(), ",")[0]
		if name == "help" {
			continue
		}
		names = append(names, name)
	}
	return
}

type Args []string

// Returns the command line arguments associated with the context.
func (c *Context) Args() Args {
	args := Args(c.flagSet.Args())
	return args
}

// Returns the nth argument, or else a blank string
func (a Args) Get(n int) string {
	if len(a) > n {
		return a[n]
	}
	return ""
}

// Returns the first argument, or else a blank string
func (a Args) First() string {
	return a.Get(0)
}

// Return the rest of the arguments (not the first one)
// or else an empty string slice
func (a Args) Tail() []string {
	if len(a) >= 2 {
		return []string(a)[1:]
	}
	return []string{}
}

// Checks if there are any arguments present
func (a Args) Present() bool {
	return len(a) != 0
}

// Swaps arguments at the given indexes
func (a Args) Swap(from, to int) error {
	if from >= len(a) || to >= len(a) {
		return errors.New("index out of range")
	}
	a[from], a[to] = a[to], a[from]
	return nil
}

func lookupInt(name string, set *flag.FlagSet) int {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.Atoi(f.Value.String())
		if err != nil {
			return 0
		}
		return val
	}

	return 0
}

func lookupDuration(name string, set *flag.FlagSet) time.Duration {
	f := set.Lookup(name)
	if f != nil {
		val, err := time.ParseDuration(f.Value.String())
		if err == nil {
			return val
		}
	}

	return 0
}

func lookupFloat64(name string, set *flag.FlagSet) float64 {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseFloat(f.Value.String(), 64)
		if err != nil {
			return 0
		}
		return val
	}

	return 0
}

func lookupString(name string, set *flag.FlagSet) string {
	f := set.Lookup(name)
	if f != nil {
		return f.Value.String()
	}

	return ""
}

func lookupStringSlice(name string, set *flag.FlagSet) []string {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*StringSlice)).Value()

	}

	return nil
}

func lookupIntSlice(name string, set *flag.FlagSet) []int {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*IntSlice)).Value()

	}

	return nil
}

func lookupGeneric(name string, set *flag.FlagSet) interface{} {
	f := set.Lookup(name)
	if f != nil {
		return f.Value
	}
	return nil
}

func lookupBool(name string, set *flag.FlagSet) bool {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseBool(f.Value.String())
		if err != nil {
			return false
		}
		return val
	}

	return false
}

func lookupBoolT(name string, set *flag.FlagSet) bool {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseBool(f.Value.String())
		if err != nil {
			return true
		}
		return val
	}

	return false
}

func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
	switch ff.Value.(type) {
	case *StringSlice:
	default:
		set.Set(name, ff.Value.String())
	}
}

func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
	visited := make(map[string]bool)
	set.Visit(func(f *flag.Flag) {
		visited[f.Name] = true
	})
	for _, f := range flags {
		parts := strings.Split(f.getName(), ",")
		if len(parts) == 1 {
			continue
		}
		var ff *flag.Flag
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if visited[name] {
				if ff != nil {
					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
				}
				ff = set.Lookup(name)
			}
		}
		if ff == nil {
			continue
		}
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if !visited[name] {
				copyFlag(name, ff, set)
			}
		}
	}
	return nil
}
<commit_msg>Add Context.GlobalFlagNames()<commit_after>package cli

import (
	"errors"
	"flag"
	"strconv"
	"strings"
	"time"
)

// Context is a type that is passed through to
// each Handler action in a cli application. Context
// can be used to retrieve context-specific Args and
// parsed command-line options.
type Context struct {
	App       *App
	Command   Command
	flagSet   *flag.FlagSet
	globalSet *flag.FlagSet
	setFlags  map[string]bool
}

// Creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
	return &Context{App: app, flagSet: set, globalSet: globalSet}
}

// Looks up the value of a local int flag, returns 0 if no int flag exists
func (c *Context) Int(name string) int {
	return lookupInt(name, c.flagSet)
}

// Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) Duration(name string) time.Duration {
	return lookupDuration(name, c.flagSet)
}

// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
func (c *Context) Float64(name string) float64 {
	return lookupFloat64(name, c.flagSet)
}

// Looks up the value of a local bool flag, returns false if no bool flag exists
func (c *Context) Bool(name string) bool {
	return lookupBool(name, c.flagSet)
}

// Looks up the value of a local boolT flag, returns false if no bool flag exists
func (c *Context) BoolT(name string) bool {
	return lookupBoolT(name, c.flagSet)
}

// Looks up the value of a local string flag, returns "" if no string flag exists
func (c *Context) String(name string) string {
	return lookupString(name, c.flagSet)
}

// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
func (c *Context) StringSlice(name string) []string {
	return lookupStringSlice(name, c.flagSet)
}

// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
func (c *Context) IntSlice(name string) []int {
	return lookupIntSlice(name, c.flagSet)
}

// Looks up the value of a local generic flag, returns nil if no generic flag exists
func (c *Context) Generic(name string) interface{} {
	return lookupGeneric(name, c.flagSet)
}

// Looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int {
	return lookupInt(name, c.globalSet)
}

// Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) GlobalDuration(name string) time.Duration {
	return lookupDuration(name, c.globalSet)
}

// Looks up the value of a global bool flag, returns false if no bool flag exists
func (c *Context) GlobalBool(name string) bool {
	return lookupBool(name, c.globalSet)
}

// Looks up the value of a global string flag, returns "" if no string flag exists
func (c *Context) GlobalString(name string) string {
	return lookupString(name, c.globalSet)
}

// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string {
	return lookupStringSlice(name, c.globalSet)
}

// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int {
	return lookupIntSlice(name, c.globalSet)
}

// Looks up the value of a global generic flag, returns nil if no generic flag exists
func (c *Context) GlobalGeneric(name string) interface{} {
	return lookupGeneric(name, c.globalSet)
}

// Determines if the flag was actually set exists
func (c *Context) IsSet(name string) bool {
	if c.setFlags == nil {
		c.setFlags = make(map[string]bool)
		c.flagSet.Visit(func(f *flag.Flag) {
			c.setFlags[f.Name] = true
		})
	}
	return c.setFlags[name] == true
}

// Returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) {
	for _, flag := range c.Command.Flags {
		name := strings.Split(flag.getName(), ",")[0]
		if name == "help" {
			continue
		}
		names = append(names, name)
	}
	return
}

// Returns a slice of global flag names used by the app.
func (c *Context) GlobalFlagNames() (names []string) {
	for _, flag := range c.App.Flags {
		name := strings.Split(flag.getName(), ",")[0]
		if name == "help" || name == "version" {
			continue
		}
		names = append(names, name)
	}
	return
}

type Args []string

// Returns the command line arguments associated with the context.
func (c *Context) Args() Args {
	args := Args(c.flagSet.Args())
	return args
}

// Returns the nth argument, or else a blank string
func (a Args) Get(n int) string {
	if len(a) > n {
		return a[n]
	}
	return ""
}

// Returns the first argument, or else a blank string
func (a Args) First() string {
	return a.Get(0)
}

// Return the rest of the arguments (not the first one)
// or else an empty string slice
func (a Args) Tail() []string {
	if len(a) >= 2 {
		return []string(a)[1:]
	}
	return []string{}
}

// Checks if there are any arguments present
func (a Args) Present() bool {
	return len(a) != 0
}

// Swaps arguments at the given indexes
func (a Args) Swap(from, to int) error {
	if from >= len(a) || to >= len(a) {
		return errors.New("index out of range")
	}
	a[from], a[to] = a[to], a[from]
	return nil
}

func lookupInt(name string, set *flag.FlagSet) int {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.Atoi(f.Value.String())
		if err != nil {
			return 0
		}
		return val
	}

	return 0
}

func lookupDuration(name string, set *flag.FlagSet) time.Duration {
	f := set.Lookup(name)
	if f != nil {
		val, err := time.ParseDuration(f.Value.String())
		if err == nil {
			return val
		}
	}

	return 0
}

func lookupFloat64(name string, set *flag.FlagSet) float64 {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseFloat(f.Value.String(), 64)
		if err != nil {
			return 0
		}
		return val
	}

	return 0
}

func lookupString(name string, set *flag.FlagSet) string {
	f := set.Lookup(name)
	if f != nil {
		return f.Value.String()
	}

	return ""
}

func lookupStringSlice(name string, set *flag.FlagSet) []string {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*StringSlice)).Value()

	}

	return nil
}

func lookupIntSlice(name string, set *flag.FlagSet) []int {
	f := set.Lookup(name)
	if f != nil {
		return (f.Value.(*IntSlice)).Value()

	}

	return nil
}

func lookupGeneric(name string, set *flag.FlagSet) interface{} {
	f := set.Lookup(name)
	if f != nil {
		return f.Value
	}
	return nil
}

func lookupBool(name string, set *flag.FlagSet) bool {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseBool(f.Value.String())
		if err != nil {
			return false
		}
		return val
	}

	return false
}

func lookupBoolT(name string, set *flag.FlagSet) bool {
	f := set.Lookup(name)
	if f != nil {
		val, err := strconv.ParseBool(f.Value.String())
		if err != nil {
			return true
		}
		return val
	}

	return false
}

func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
	switch ff.Value.(type) {
	case *StringSlice:
	default:
		set.Set(name, ff.Value.String())
	}
}

func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
	visited := make(map[string]bool)
	set.Visit(func(f *flag.Flag) {
		visited[f.Name] = true
	})
	for _, f := range flags {
		parts := strings.Split(f.getName(), ",")
		if len(parts) == 1 {
			continue
		}
		var ff *flag.Flag
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if visited[name] {
				if ff != nil {
					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
				}
				ff = set.Lookup(name)
			}
		}
		if ff == nil {
			continue
		}
		for _, name := range parts {
			name = strings.Trim(name, " ")
			if !visited[name] {
				copyFlag(name, ff, set)
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package webapp

import (
	"fmt"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/mbict/binding"
	"github.com/mbict/render"
)

type Context struct {
	Request  *http.Request
	Response ResponseWriter
	Params   httprouter.Params
	Errors   Errors

	values   map[interface{}]interface{}
	handlers []HandlerFunc
	index    int8
	engine   *Engine
}

/************************************/
/********** CONTEXT CREATION ********/
/************************************/

func (engine *Engine) createContext(rw http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Context {
	return &Context{
		Response: newResponseWriter(rw),
		Request:  req,
		Params:   params,
		handlers: handlers,
		Errors:   nil,
		index:    -1,
		engine:   engine,
	}
}

/************************************/
/*************** FLOW ***************/
/************************************/

// Next should be used only in the middlewares.
// It executes the pending handlers in the chain inside the calling handler.
// See example in github.
func (ctx *Context) Next() {
	ctx.index++
	s := int8(len(ctx.handlers))
	for ; ctx.index < s; ctx.index++ {
		ctx.handlers[ctx.index](ctx)
	}
}

// Forces the system to do not continue calling the pending handlers in the chain.
func (ctx *Context) Abort() {
	ctx.index = AbortIndex
}

/************************************/
/******** METADATA MANAGEMENT********/
/************************************/

// Sets a new pair key/value just for the specified context.
// It also lazy initializes the hashmap.
func (ctx *Context) Set(key interface{}, item interface{}) {
	if ctx.values == nil {
		ctx.values = make(map[interface{}]interface{})
	}
	ctx.values[key] = item
}

// Get returns the value for the given key or an error if the key does not exist.
func (ctx *Context) Get(key interface{}) interface{} {
	if ctx.values != nil {
		value, ok := ctx.values[key]
		if ok {
			return value
		}
	}
	return nil
}

func (ctx *Context) GetOk(key interface{}) (interface{}, bool) {
	if ctx.values != nil {
		value, ok := ctx.values[key]
		if ok {
			return value, true
		}
	}
	return nil, false
}

func (ctx *Context) ClientIP() string {
	return ctx.Request.RemoteAddr
}

/************************************/
/********* PARSING REQUEST **********/
/************************************/
func (ctx *Context) Bind(obj interface{}) binding.Errors {
	return binding.Bind(obj, ctx.Request)
}

func (ctx *Context) BindWith(obj interface{}, b binding.Binding) binding.Errors {
	return b.Bind(obj, ctx.Request)
}

/************************************/
/******** RESPONSE RENDERING ********/
/************************************/

func (ctx *Context) Render(code int, render render.Render, obj ...interface{}) {
	if err := render.Render(ctx.Response, code, obj...); err != nil {
		panic(err)
	}
}

// Serializes the given struct as JSON into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/json".
func (ctx *Context) JSON(code int, obj interface{}) {
	ctx.Render(code, render.JSON, obj)
}

// Serializes the given struct as XML into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/xml".
func (ctx *Context) XML(code int, obj interface{}) {
	ctx.Render(code, render.XML, obj)
}

// Renders the HTTP template specified by its file name.
// It also updates the HTTP code and sets the Content-Type as "text/html".
// See http://golang.org/doc/articles/wiki/
func (ctx *Context) HTML(code int, name string, obj ...interface{}) {
	ctx.Render(code, ctx.engine.templateRender, name, obj)
}

// Writes the given string into the response body and sets the Content-Type to "text/plain".
func (ctx *Context) String(code int, format string, values ...interface{}) {
	ctx.Render(code, render.Plain, format, values)
}

// Writes the given string into the response body and sets the Content-Type to "text/html" without template.
func (ctx *Context) HTMLString(code int, format string, values ...interface{}) {
	ctx.Render(code, render.HtmlPlain, format, values)
}

// Returns a HTTP redirect to the specific location.
func (ctx *Context) Redirect(code int, location string) {
	if code >= 300 && code <= 308 {
		ctx.Render(code, render.Redirect, location)
	} else {
		panic(fmt.Sprintf("Cannot send a redirect with status code %d", code))
	}
}

// Writes some data into the body stream and updates the HTTP code.
func (ctx *Context) Data(code int, contentType string, data []byte) {
	if len(contentType) > 0 {
		ctx.Response.Header().Set("Content-Type", contentType)
	}
	ctx.Response.WriteHeader(code)
	ctx.Response.Write(data)
}

// Writes the specified file into the body stream
func (ctx *Context) File(filepath string) {
	http.ServeFile(ctx.Response, ctx.Request, filepath)
}
<commit_msg>Typo in param passing in context render helper functions<commit_after>package webapp

import (
	"fmt"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"github.com/mbict/binding"
	"github.com/mbict/render"
)

type Context struct {
	Request  *http.Request
	Response ResponseWriter
	Params   httprouter.Params
	Errors   Errors

	values   map[interface{}]interface{}
	handlers []HandlerFunc
	index    int8
	engine   *Engine
}

/************************************/
/********** CONTEXT CREATION ********/
/************************************/

func (engine *Engine) createContext(rw http.ResponseWriter, req *http.Request, params httprouter.Params, handlers []HandlerFunc) *Context {
	return &Context{
		Response: newResponseWriter(rw),
		Request:  req,
		Params:   params,
		handlers: handlers,
		Errors:   nil,
		index:    -1,
		engine:   engine,
	}
}

/************************************/
/*************** FLOW ***************/
/************************************/

// Next should be used only in the middlewares.
// It executes the pending handlers in the chain inside the calling handler.
// See example in github.
func (ctx *Context) Next() {
	ctx.index++
	s := int8(len(ctx.handlers))
	for ; ctx.index < s; ctx.index++ {
		ctx.handlers[ctx.index](ctx)
	}
}

// Forces the system to do not continue calling the pending handlers in the chain.
func (ctx *Context) Abort() {
	ctx.index = AbortIndex
}

/************************************/
/******** METADATA MANAGEMENT********/
/************************************/

// Sets a new pair key/value just for the specified context.
// It also lazy initializes the hashmap.
func (ctx *Context) Set(key interface{}, item interface{}) {
	if ctx.values == nil {
		ctx.values = make(map[interface{}]interface{})
	}
	ctx.values[key] = item
}

// Get returns the value for the given key or an error if the key does not exist.
func (ctx *Context) Get(key interface{}) interface{} {
	if ctx.values != nil {
		value, ok := ctx.values[key]
		if ok {
			return value
		}
	}
	return nil
}

func (ctx *Context) GetOk(key interface{}) (interface{}, bool) {
	if ctx.values != nil {
		value, ok := ctx.values[key]
		if ok {
			return value, true
		}
	}
	return nil, false
}

func (ctx *Context) ClientIP() string {
	return ctx.Request.RemoteAddr
}

/************************************/
/********* PARSING REQUEST **********/
/************************************/
func (ctx *Context) Bind(obj interface{}) binding.Errors {
	return binding.Bind(obj, ctx.Request)
}

func (ctx *Context) BindWith(obj interface{}, b binding.Binding) binding.Errors {
	return b.Bind(obj, ctx.Request)
}

/************************************/
/******** RESPONSE RENDERING ********/
/************************************/

func (ctx *Context) Render(code int, render render.Render, obj ...interface{}) {
	if err := render.Render(ctx.Response, code, obj...); err != nil {
		panic(err)
	}
}

// Serializes the given struct as JSON into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/json".
func (ctx *Context) JSON(code int, obj interface{}) {
	ctx.Render(code, render.JSON, obj)
}

// Serializes the given struct as XML into the response body in a fast and efficient way.
// It also sets the Content-Type as "application/xml".
func (ctx *Context) XML(code int, obj interface{}) {
	ctx.Render(code, render.XML, obj)
}

// Renders the HTTP template specified by its file name.
// It also updates the HTTP code and sets the Content-Type as "text/html".
// See http://golang.org/doc/articles/wiki/
func (ctx *Context) HTML(code int, name string, obj ...interface{}) {
	ctx.Render(code, ctx.engine.templateRender, append([]interface{}{name}, obj...)...)
}

// Writes the given string into the response body and sets the Content-Type to "text/plain".
func (ctx *Context) String(code int, format string, values ...interface{}) {
	ctx.Render(code, render.Plain, append([]interface{}{format}, values...)...)
}

// Writes the given string into the response body and sets the Content-Type to "text/html" without template.
func (ctx *Context) HTMLString(code int, format string, values ...interface{}) {
	ctx.Render(code, render.HtmlPlain, append([]interface{}{format}, values...)...)
}

// Returns a HTTP redirect to the specific location.
func (ctx *Context) Redirect(code int, location string) {
	if code >= 300 && code <= 308 {
		ctx.Render(code, render.Redirect, location)
	} else {
		panic(fmt.Sprintf("Cannot send a redirect with status code %d", code))
	}
}

// Writes some data into the body stream and updates the HTTP code.
func (ctx *Context) Data(code int, contentType string, data []byte) {
	if len(contentType) > 0 {
		ctx.Response.Header().Set("Content-Type", contentType)
	}
	ctx.Response.WriteHeader(code)
	ctx.Response.Write(data)
}

// Writes the specified file into the body stream
func (ctx *Context) File(filepath string) {
	http.ServeFile(ctx.Response, ctx.Request, filepath)
}
<|endoftext|>


<commit_before>package shortlink

import (
	"database/sql"
	"db"
	"errors"
	"fmt"
	"regexp"
)

// checks if a id already exists in the database
func checkIDConflict(id string) (bool, error) {
	collision := 1
	err := db.Db.QueryRow("SELECT EXISTS(SELECT 1 FROM links WHERE id=?)", id).Scan(&collision)
	return collision != 0, err
}

// gets a unique id for a new game
func getUniqueID() (string, error) {
	var count uint
	var scale uint
	var addConst uint
	var newID uint
	var idString string

	conflict := true
	err := db.Db.QueryRow("SELECT count, scale, addConst FROM count WHERE type='links'").Scan(&count, &scale, &addConst)
	if err != nil {
		return "", err
	}

	for conflict {
		count += 1
		newID = (count*scale + addConst) % 65536
		idString = fmt.Sprintf("%x", newID)
		// makes 4 wide
		for len(idString) < 4 {
			idString = "0" + idString
		}
		conflict, err = checkIDConflict(idString)
		if err != nil {
			return "", err
		}
	}

	updateCount, err := db.Db.Prepare("UPDATE count SET count=? WHERE type='links'")
	if err != nil {
		return idString, err
	}

	_, err = updateCount.Exec(count)
	if err != nil {
		return idString, err
	}

	return idString, nil
}

// adds the game into the database
func Add(link string) (string, error) {
	err := db.Db.Ping()
	if err != nil {
		return "", err
	}

	idString, err := getUniqueID()
	if err != nil {
		return "", err
	}

	addLink, err := db.Db.Prepare("INSERT INTO links VALUES(?, ?)")
	if err != nil {
		return "", err
	}
	_, err = addLink.Exec(idString, link)
	return idString, err
}

// adds the game into the database
func Get(id string) (string, error) {
	err := db.Db.Ping()
	if err != nil {
		return "", err
	}

	if bad, err := regexp.MatchString("[^a-f0-9]", id); err != nil {
		return "", err
	} else if bad {
		return "", errors.New("Invalid link ID")
	}

	var link string

	//TODO: handle NULLS
	err = db.Db.QueryRow("SELECT link FROM links WHERE id=?", id).Scan(&link)
	if err != nil {
		if err == sql.ErrNoRows {
			return "", errors.New("Link not found")
		}
		return "", err
	}

	return link, nil
}
<commit_msg>changed shortlinks to accept uppercase<commit_after>package shortlink

import (
	"database/sql"
	"db"
	"errors"
	"fmt"
	"regexp"
	"strings"
)

// checks if a id already exists in the database
func checkIDConflict(id string) (bool, error) {
	collision := 1
	err := db.Db.QueryRow("SELECT EXISTS(SELECT 1 FROM links WHERE id=?)", id).Scan(&collision)
	return collision != 0, err
}

// gets a unique id for a new game
func getUniqueID() (string, error) {
	var count uint
	var scale uint
	var addConst uint
	var newID uint
	var idString string

	conflict := true
	err := db.Db.QueryRow("SELECT count, scale, addConst FROM count WHERE type='links'").Scan(&count, &scale, &addConst)
	if err != nil {
		return "", err
	}

	for conflict {
		count += 1
		newID = (count*scale + addConst) % 65536
		idString = fmt.Sprintf("%x", newID)
		// makes 4 wide
		for len(idString) < 4 {
			idString = "0" + idString
		}
		conflict, err = checkIDConflict(idString)
		if err != nil {
			return "", err
		}
	}

	updateCount, err := db.Db.Prepare("UPDATE count SET count=? WHERE type='links'")
	if err != nil {
		return idString, err
	}

	_, err = updateCount.Exec(count)
	if err != nil {
		return idString, err
	}

	return idString, nil
}

// adds the game into the database
func Add(link string) (string, error) {
	err := db.Db.Ping()
	if err != nil {
		return "", err
	}

	idString, err := getUniqueID()
	if err != nil {
		return "", err
	}

	addLink, err := db.Db.Prepare("INSERT INTO links VALUES(?, ?)")
	if err != nil {
		return "", err
	}
	_, err = addLink.Exec(idString, link)
	return idString, err
}

// adds the game into the database
func Get(id string) (string, error) {
	err := db.Db.Ping()
	if err != nil {
		return "", err
	}

	id = strings.ToLower(id)

	if bad, err := regexp.MatchString("[^a-f0-9]", id); err != nil {
		return "", err
	} else if bad {
		return "", errors.New("Invalid link ID")
	}

	var link string

	//TODO: handle NULLS
	err = db.Db.QueryRow("SELECT link FROM links WHERE id=?", id).Scan(&link)
	if err != nil {
		if err == sql.ErrNoRows {
			return "", errors.New("Link not found")
		}
		return "", err
	}

	return link, nil
}
<|endoftext|>


<commit_before>// Copyright 2018 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package collateral

import (
	"bytes"
	"fmt"
	"html"
	"os"
	"sort"
	"strings"

	"strconv"

	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
	"github.com/spf13/pflag"
)

// Control determines the behavior of the EmitCollateral function
type Control struct {
	// OutputDir specifies the directory to output the collateral files
	OutputDir string

	// EmitManPages controls whether to produce man pages.
	EmitManPages bool

	// EmitYAML controls whether to produce YAML files.
	EmitYAML bool

	// EmitBashCompletion controls whether to produce bash completion files.
	EmitBashCompletion bool

	// EmitMarkdown controls whether to produce mankdown documentation files.
	EmitMarkdown bool

	// EmitJeyllHTML controls whether to produce Jekyll-friendly HTML documentation files.
	EmitJekyllHTML bool

	// ManPageInfo provides extra information necessary when emitting man pages.
	ManPageInfo doc.GenManHeader
}

// EmitCollateral produces a set of collateral files for a CLI command. You can
// select to emit markdown to describe a command's function, man pages, YAML
// descriptions, and bash completion files.
func EmitCollateral(root *cobra.Command, c *Control) error {
	if c.EmitManPages {
		if err := doc.GenManTree(root, &c.ManPageInfo, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output manpage tree: %v", err)
		}
	}

	if c.EmitMarkdown {
		if err := doc.GenMarkdownTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output markdown tree: %v", err)
		}
	}

	if c.EmitJekyllHTML {
		if err := genJekyllHTML(root, c.OutputDir+"/"+root.Name()+".html"); err != nil {
			return fmt.Errorf("unable to output Jekyll HTML file: %v", err)
		}
	}

	if c.EmitYAML {
		if err := doc.GenYamlTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output YAML tree: %v", err)
		}
	}

	if c.EmitBashCompletion {
		if err := root.GenBashCompletionFile(c.OutputDir + "/" + root.Name() + ".bash"); err != nil {
			return fmt.Errorf("unable to output bash completion file: %v", err)
		}
	}

	return nil
}

type generator struct {
	buffer *bytes.Buffer
}

func (g *generator) emit(str ...string) {
	for _, s := range str {
		g.buffer.WriteString(s)
	}
	g.buffer.WriteByte('\n')
}

func findCommands(commands map[string]*cobra.Command, cmd *cobra.Command) {
	cmd.InitDefaultHelpCmd()
	cmd.InitDefaultHelpFlag()

	commands[cmd.CommandPath()] = cmd
	for _, c := range cmd.Commands() {
		findCommands(commands, c)
	}
}

const help = "help"

func genJekyllHTML(cmd *cobra.Command, path string) error {
	commands := make(map[string]*cobra.Command)
	findCommands(commands, cmd)

	names := make([]string, len(commands), len(commands))
	i := 0
	for n := range commands {
		names[i] = n
		i++
	}
	sort.Strings(names)

	g := &generator{
		buffer: &bytes.Buffer{},
	}

	count := 0
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		count++
	}

	g.genFileHeader(cmd, count)
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		g.genCommand(commands[n])
	}

	f, err := os.Create(path)
	if err != nil {
		return err
	}
	_, err = g.buffer.WriteTo(f)
	_ = f.Close()

	return err
}

func (g *generator) genFileHeader(root *cobra.Command, numEntries int) {
	g.emit("---")
	g.emit("title: ", root.Name())
	g.emit("overview: ", html.EscapeString(root.Short))
	g.emit("layout: pkg-collateral-docs")
	g.emit("number_of_entries: ", strconv.Itoa(numEntries))
	g.emit("---")
}

func (g *generator) genCommand(cmd *cobra.Command) {
	if cmd.Hidden || cmd.Deprecated != "" {
		return
	}

	if cmd.HasParent() {
		g.emit("
", cmd.CommandPath(), "
")
	}

	if cmd.Long != "" {
		g.emitText(cmd.Long)
	} else if cmd.Short != "" {
		g.emitText(cmd.Short)
	}

	if cmd.Runnable() {
		g.emit("
", html.EscapeString(cmd.UseLine()))
		g.emit("
")
	}

	// TODO: output aliases

	flags := cmd.NonInheritedFlags()
	flags.SetOutput(g.buffer)

	parentFlags := cmd.InheritedFlags()
	parentFlags.SetOutput(g.buffer)

	if flags.HasFlags() || parentFlags.HasFlags() {
		g.emit("
")
		g.emit("
")
		g.emit("Flags	")
		g.emit("Shorthand	")
		g.emit("Description	")
		g.emit("
")
		g.emit("
")

		f := make(map[string]*pflag.Flag)
		addFlags(f, flags)
		addFlags(f, parentFlags)

		names := make([]string, len(f))
		i := 0
		for n := range f {
			names[i] = n
			i++
		}
		sort.Strings(names)

		for _, n := range names {
			g.genFlag(f[n])
		}

		g.emit("
")
		g.emit("
")
	}

	if len(cmd.Example) > 0 {
		g.emit("
", "Examples", "
")
		g.emit("
", html.EscapeString(cmd.Example))
		g.emit("
")
	}
}

func addFlags(f map[string]*pflag.Flag, s *pflag.FlagSet) {
	s.VisitAll(func(flag *pflag.Flag) {
		if flag.Deprecated != "" || flag.Hidden {
			return
		}

		if flag.Name == help {
			return
		}

		f[flag.Name] = flag
	})
}

func (g *generator) genFlag(flag *pflag.Flag) {
	varname, usage := unquoteUsage(flag)
	if varname != "" {
		varname = " <" + varname + ">"
	}

	def := ""
	if flag.Value.Type() == "string" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	} else if flag.Value.Type() != "bool" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	}

	g.emit("
")
	g.emit("", "--", flag.Name, html.EscapeString(varname), "	")
	if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
		g.emit("", "-", flag.Shorthand, "	")
	} else {
		g.emit("	")
	}
	g.emit("", html.EscapeString(usage), " ", def, "	")
	g.emit("
")
}

func (g *generator) emitText(text string) {
	paras := strings.Split(text, "\n\n")
	for _, p := range paras {
		g.emit("
", html.EscapeString(p), "
")
	}
}

// unquoteUsage extracts a back-quoted name from the usage
// string for a flag and returns it and the un-quoted usage.
// Given "a `name` to show" it returns ("name", "a name to show").
// If there are no back quotes, the name is an educated guess of the
// type of the flag's value, or the empty string if the flag is boolean.
func unquoteUsage(flag *pflag.Flag) (name string, usage string) {
	// Look for a back-quoted name, but avoid the strings package.
	usage = flag.Usage
	for i := 0; i < len(usage); i++ {
		if usage[i] == '`' {
			for j := i + 1; j < len(usage); j++ {
				if usage[j] == '`' {
					name = usage[i+1 : j]
					usage = usage[:i] + name + usage[j+1:]
					return name, usage
				}
			}
			break // Only one back quote; use type name.
		}
	}

	name = flag.Value.Type()
	switch name {
	case "bool":
		name = ""
	case "float64":
		name = "float"
	case "int64":
		name = "int"
	case "uint64":
		name = "uint"
	}

	return
}
<commit_msg>Run bin/fmt.sh (#3251)<commit_after>// Copyright 2018 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package collateral

import (
	"bytes"
	"fmt"
	"html"
	"os"
	"sort"
	"strconv"
	"strings"

	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
	"github.com/spf13/pflag"
)

// Control determines the behavior of the EmitCollateral function
type Control struct {
	// OutputDir specifies the directory to output the collateral files
	OutputDir string

	// EmitManPages controls whether to produce man pages.
	EmitManPages bool

	// EmitYAML controls whether to produce YAML files.
	EmitYAML bool

	// EmitBashCompletion controls whether to produce bash completion files.
	EmitBashCompletion bool

	// EmitMarkdown controls whether to produce mankdown documentation files.
	EmitMarkdown bool

	// EmitJeyllHTML controls whether to produce Jekyll-friendly HTML documentation files.
	EmitJekyllHTML bool

	// ManPageInfo provides extra information necessary when emitting man pages.
	ManPageInfo doc.GenManHeader
}

// EmitCollateral produces a set of collateral files for a CLI command. You can
// select to emit markdown to describe a command's function, man pages, YAML
// descriptions, and bash completion files.
func EmitCollateral(root *cobra.Command, c *Control) error {
	if c.EmitManPages {
		if err := doc.GenManTree(root, &c.ManPageInfo, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output manpage tree: %v", err)
		}
	}

	if c.EmitMarkdown {
		if err := doc.GenMarkdownTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output markdown tree: %v", err)
		}
	}

	if c.EmitJekyllHTML {
		if err := genJekyllHTML(root, c.OutputDir+"/"+root.Name()+".html"); err != nil {
			return fmt.Errorf("unable to output Jekyll HTML file: %v", err)
		}
	}

	if c.EmitYAML {
		if err := doc.GenYamlTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output YAML tree: %v", err)
		}
	}

	if c.EmitBashCompletion {
		if err := root.GenBashCompletionFile(c.OutputDir + "/" + root.Name() + ".bash"); err != nil {
			return fmt.Errorf("unable to output bash completion file: %v", err)
		}
	}

	return nil
}

type generator struct {
	buffer *bytes.Buffer
}

func (g *generator) emit(str ...string) {
	for _, s := range str {
		g.buffer.WriteString(s)
	}
	g.buffer.WriteByte('\n')
}

func findCommands(commands map[string]*cobra.Command, cmd *cobra.Command) {
	cmd.InitDefaultHelpCmd()
	cmd.InitDefaultHelpFlag()

	commands[cmd.CommandPath()] = cmd
	for _, c := range cmd.Commands() {
		findCommands(commands, c)
	}
}

const help = "help"

func genJekyllHTML(cmd *cobra.Command, path string) error {
	commands := make(map[string]*cobra.Command)
	findCommands(commands, cmd)

	names := make([]string, len(commands), len(commands))
	i := 0
	for n := range commands {
		names[i] = n
		i++
	}
	sort.Strings(names)

	g := &generator{
		buffer: &bytes.Buffer{},
	}

	count := 0
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		count++
	}

	g.genFileHeader(cmd, count)
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		g.genCommand(commands[n])
	}

	f, err := os.Create(path)
	if err != nil {
		return err
	}
	_, err = g.buffer.WriteTo(f)
	_ = f.Close()

	return err
}

func (g *generator) genFileHeader(root *cobra.Command, numEntries int) {
	g.emit("---")
	g.emit("title: ", root.Name())
	g.emit("overview: ", html.EscapeString(root.Short))
	g.emit("layout: pkg-collateral-docs")
	g.emit("number_of_entries: ", strconv.Itoa(numEntries))
	g.emit("---")
}

func (g *generator) genCommand(cmd *cobra.Command) {
	if cmd.Hidden || cmd.Deprecated != "" {
		return
	}

	if cmd.HasParent() {
		g.emit("
", cmd.CommandPath(), "
")
	}

	if cmd.Long != "" {
		g.emitText(cmd.Long)
	} else if cmd.Short != "" {
		g.emitText(cmd.Short)
	}

	if cmd.Runnable() {
		g.emit("
", html.EscapeString(cmd.UseLine()))
		g.emit("
")
	}

	// TODO: output aliases

	flags := cmd.NonInheritedFlags()
	flags.SetOutput(g.buffer)

	parentFlags := cmd.InheritedFlags()
	parentFlags.SetOutput(g.buffer)

	if flags.HasFlags() || parentFlags.HasFlags() {
		g.emit("
")
		g.emit("
")
		g.emit("Flags	")
		g.emit("Shorthand	")
		g.emit("Description	")
		g.emit("
")
		g.emit("
")

		f := make(map[string]*pflag.Flag)
		addFlags(f, flags)
		addFlags(f, parentFlags)

		names := make([]string, len(f))
		i := 0
		for n := range f {
			names[i] = n
			i++
		}
		sort.Strings(names)

		for _, n := range names {
			g.genFlag(f[n])
		}

		g.emit("
")
		g.emit("
")
	}

	if len(cmd.Example) > 0 {
		g.emit("
", "Examples", "
")
		g.emit("
", html.EscapeString(cmd.Example))
		g.emit("
")
	}
}

func addFlags(f map[string]*pflag.Flag, s *pflag.FlagSet) {
	s.VisitAll(func(flag *pflag.Flag) {
		if flag.Deprecated != "" || flag.Hidden {
			return
		}

		if flag.Name == help {
			return
		}

		f[flag.Name] = flag
	})
}

func (g *generator) genFlag(flag *pflag.Flag) {
	varname, usage := unquoteUsage(flag)
	if varname != "" {
		varname = " <" + varname + ">"
	}

	def := ""
	if flag.Value.Type() == "string" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	} else if flag.Value.Type() != "bool" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	}

	g.emit("
")
	g.emit("", "--", flag.Name, html.EscapeString(varname), "	")
	if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
		g.emit("", "-", flag.Shorthand, "	")
	} else {
		g.emit("	")
	}
	g.emit("", html.EscapeString(usage), " ", def, "	")
	g.emit("
")
}

func (g *generator) emitText(text string) {
	paras := strings.Split(text, "\n\n")
	for _, p := range paras {
		g.emit("
", html.EscapeString(p), "
")
	}
}

// unquoteUsage extracts a back-quoted name from the usage
// string for a flag and returns it and the un-quoted usage.
// Given "a `name` to show" it returns ("name", "a name to show").
// If there are no back quotes, the name is an educated guess of the
// type of the flag's value, or the empty string if the flag is boolean.
func unquoteUsage(flag *pflag.Flag) (name string, usage string) {
	// Look for a back-quoted name, but avoid the strings package.
	usage = flag.Usage
	for i := 0; i < len(usage); i++ {
		if usage[i] == '`' {
			for j := i + 1; j < len(usage); j++ {
				if usage[j] == '`' {
					name = usage[i+1 : j]
					usage = usage[:i] + name + usage[j+1:]
					return name, usage
				}
			}
			break // Only one back quote; use type name.
		}
	}

	name = flag.Value.Type()
	switch name {
	case "bool":
		name = ""
	case "float64":
		name = "float"
	case "int64":
		name = "int"
	case "uint64":
		name = "uint"
	}

	return
}
<|endoftext|>


<commit_before>// Copyright 2011 Miek Gieben. All rights reserved.
// Lisenced under the GPLv2

/*
Funkensturm rewrites DNS packets in the broadest sense of the word.
The rewriting can include delayed (re)sending of packets, (re)sending
packets to multiple servers, rewriting the packet contents, for instance
by signing a packet, or the other way around, stripping the signatures.

In its essence this is no different that a recursive nameserver, which also
receives and sends queries. The difference is the huge amount of tweaking
Funkensturm offers.

The configuration of Funkensturm is done by writing it in Go - a
separate configuration language was deemed to be unpractical and
would limit the possibilities.

Usage:
        funkensturm [flags]

The flags are:

        -sserver
                        Listener address and port for the server. This has to be
                        specified as: address:port, for instance 127.0.0.1:8053.
                        This is also the default.
        -rserver
                        Remote server address in address:port format. This can be
                        repeated, for each rserver a resolver channel is created.
                        The first begin `qr[0]`, the second `qr[1]`, etc.
                        The default is: 127.0.0.1:53

Debugging flags:

        -verbose
                        Print packets as they flow through Funkensturm.

Predefined configurations are shown in `config_delay.go` and `config_sign.go`. The
default `config.go` implements a transparant proxy.

Also see: http://www.miek.nl/blog/archives/2011/01/23/funkensturm/index.html for
a architectural overview.

In FunkenSturm you define chains named Funk's (maybe just 'chain' is a better name). Each Funk
consi

*/
package documentation
<commit_msg>More docs<commit_after>// Copyright 2011 Miek Gieben. All rights reserved.
// Lisenced under the GPLv2

/*
Funkensturm rewrites DNS packets in the broadest sense of the word.
The rewriting can include delayed (re)sending of packets, (re)sending
packets to multiple servers, rewriting the packet contents, for instance
by signing a packet, or the other way around, stripping the signatures.

In its essence this is no different that a recursive nameserver, which also
receives and sends queries. The difference is the huge amount of tweaking
Funkensturm offers.

The configuration of Funkensturm is done by writing it in Go - a
separate configuration language was deemed to be unpractical and
would limit the possibilities.

Usage:
        funkensturm [flags]

The flags are:

        -sserver
                        Listener address and port for the server. This has to be
                        specified as: address:port, for instance 127.0.0.1:8053.
                        This is also the default.
        -rserver
                        Remote server address in address:port format. This can be
                        repeated, for each rserver a resolver channel is created.
                        The first begin `qr[0]`, the second `qr[1]`, etc.
                        The default is: 127.0.0.1:53

Debugging flags:

        -verbose
                        Print packets as they flow through Funkensturm.

Predefined configurations are shown in `config_delay.go` and `config_sign.go`. The
default `config.go` implements a transparant proxy.

Also see: http://www.miek.nl/blog/archives/2011/01/23/funkensturm/index.html for
a architectural overview.

In FunkenSturm you define chains named Funk's (maybe just 'chain' is a better name). Each Funk
consists out of match and action function. If the match function matches (return true) the
action function is called.
Multiple Funk's may be used. The first 'true' value win and that action function is performed.

*/
package documentation
<|endoftext|>


<commit_before>package goinsta

import (
	"encoding/json"
	"fmt"
	"strconv"
)

// Item represents media items
type Item struct {
	TakenAt          int     `json:"taken_at"`
	ID               int64   `json:"pk"`
	IDStr            string  `json:"id"`
	DeviceTimestamp  int64   `json:"device_timestamp"`
	MediaType        int     `json:"media_type"`
	Code             string  `json:"code"`
	ClientCacheKey   string  `json:"client_cache_key"`
	FilterType       int     `json:"filter_type"`
	CarouselParentID string  `json:"carousel_parent_id"`
	CarouselMedia    []Item  `json:"carousel_media,omitempty"`
	User             User    `json:"user"`
	CanViewerReshare bool    `json:"can_viewer_reshare"`
	Caption          Caption `json:"caption"`
	CaptionIsEdited  bool    `json:"caption_is_edited"`
	Likes            int     `json:"like_count"`
	HasLiked         bool    `json:"has_liked"`
	// TopLikers can be multiple data
	TopLikersStr                 string `json:"top_likers,string"`
	TopLikers                    []User `json:"top_likers"`
	CommentLikesEnabled          bool   `json:"comment_likes_enabled"`
	CommentThreadingEnabled      bool   `json:"comment_threading_enabled"`
	HasMoreComments              bool   `json:"has_more_comments"`
	MaxNumVisiblePreviewComments int    `json:"max_num_visible_preview_comments"`
	// PreviewComments can be `string` or `[]string`
	PreviewComments      []interface{} `json:"preview_comments,omitempty"`
	CommentCount         int           `json:"comment_count"`
	PhotoOfYou           bool          `json:"photo_of_you"`
	Usertags             Tag           `json:"usertags,omitempty"`
	FbUserTags           Tag           `json:"fb_user_tags"`
	CanViewerSave        bool          `json:"can_viewer_save"`
	OrganicTrackingToken string        `json:"organic_tracking_token"`
	Images               Images        `json:"image_versions2,omitempty"`
	OriginalWidth        int           `json:"original_width,omitempty"`
	OriginalHeight       int           `json:"original_height,omitempty"`
	ImportedTakenAt      int           `json:"imported_taken_at,omitempty"`

	// Only for stories
	StoryEvents              []interface{} `json:"story_events"`
	StoryHashtags            []interface{} `json:"story_hashtags"`
	StoryPolls               []interface{} `json:"story_polls"`
	StoryFeedMedia           []interface{} `json:"story_feed_media"`
	StorySoundOn             []interface{} `json:"story_sound_on"`
	CreativeConfig           interface{}   `json:"creative_config"`
	StoryLocations           []interface{} `json:"story_locations"`
	StorySliders             []interface{} `json:"story_sliders"`
	StoryQuestions           []interface{} `json:"story_questions"`
	StoryProductItems        []interface{} `json:"story_product_items"`
	SupportsReelReactions    bool          `json:"supports_reel_reactions"`
	ShowOneTapFbShareTooltip bool          `json:"show_one_tap_fb_share_tooltip"`
	HasSharedToFb            int           `json:"has_shared_to_fb"`
	Mentions                 []Mentions
	Videos                   []Videos `json:"video_versions,omitempty"`
	HasAudio                 bool     `json:"has_audio,omitempty"`
	VideoDuration            float64  `json:"video_duration,omitempty"`
	IsDashEligible           int      `json:"is_dash_eligible,omitempty"`
	VideoDashManifest        string   `json:"video_dash_manifest,omitempty"`
	NumberOfQualities        int      `json:"number_of_qualities,omitempty"`
}

type Media interface {
	Next() error
}

type StoryMedia struct {
	inst     *Instagram
	endpoint string
	uid      int64

	ID              int      `json:"id"`
	LatestReelMedia int      `json:"latest_reel_media"`
	ExpiringAt      int      `json:"expiring_at"`
	Seen            float64  `json:"seen"`
	CanReply        bool     `json:"can_reply"`
	CanReshare      bool     `json:"can_reshare"`
	ReelType        string   `json:"reel_type"`
	User            User     `json:"user"`
	Items           []Item   `json:"items"`
	ReelMentions    []string `json:"reel_mentions"`
	PrefetchCount   int      `json:"prefetch_count"`
	HasBestiesMedia bool     `json:"has_besties_media"`
	Status          string   `json:"status"`
}

// Next allows to paginate after calling:
// User.Stories
func (media *StoryMedia) Next() (err error) {
	var body []byte
	insta := media.inst
	endpoint := media.endpoint

	if media.uid != 0 {
		endpoint = fmt.Sprintf(endpoint, media.uid)
	}
	body, err = insta.sendSimpleRequest(endpoint)
	if err == nil {
		m := StoryMedia{}
		err = json.Unmarshal(body, &m)
		if err == nil {
			err = ErrNoMore
			*media = m
			media.inst = insta
			media.endpoint = endpoint
			// TODO check NextID media
		}
	}
	return err
}

// Media represent a set of media items
type FeedMedia struct {
	inst *Instagram

	uid      int64
	endpoint string

	Items               []Item `json:"items"`
	NumResults          int    `json:"num_results"`
	MoreAvailable       bool   `json:"more_available"`
	AutoLoadMoreEnabled bool   `json:"auto_load_more_enabled"`
	Status              string `json:"status"`
	// Can be int64 and string
	// this is why recomend Next() usage :')
	NextID interface{} `json:"next_max_id"`
}

// Next allows to paginate after calling:
// User.Feed
//
// returns ErrNoMore when list reach the end.
func (media *FeedMedia) Next() (err error) {
	var body []byte
	insta := media.inst
	endpoint := media.endpoint
	next := ""

	switch s := media.NextID.(type) {
	case string:
		next = s
	case int64:
		next = strconv.FormatInt(s, 10)
	}

	if media.uid != 0 {
		endpoint = fmt.Sprintf(endpoint, media.uid)
	}

	body, err = insta.sendRequest(
		&reqOptions{
			Endpoint: endpoint,
			Query: map[string]string{
				"max_id":         next,
				"rank_token":     insta.rankToken,
				"min_timestamp":  "",
				"ranked_content": "true",
			},
		},
	)
	if err == nil {
		m := FeedMedia{}
		err = json.Unmarshal(body, &m)
		if err == nil {
			*media = m
			media.inst = insta
			media.endpoint = endpoint
			if m.NextID == 0 || !m.MoreAvailable {
				err = ErrNoMore
			}
		}
	}
	return err
}
<commit_msg>Fixed type errors<commit_after>package goinsta

import (
	"encoding/json"
	"fmt"
	"strconv"
)

// Item represents media items
//
// All Item has
type Item struct {
	TakenAt          int     `json:"taken_at"`
	ID               int64   `json:"pk"`
	IDStr            string  `json:"id"`
	DeviceTimestamp  int64   `json:"device_timestamp"`
	MediaType        int     `json:"media_type"`
	Code             string  `json:"code"`
	ClientCacheKey   string  `json:"client_cache_key"`
	FilterType       int     `json:"filter_type"`
	CarouselParentID string  `json:"carousel_parent_id"`
	CarouselMedia    []Item  `json:"carousel_media,omitempty"`
	User             User    `json:"user"`
	CanViewerReshare bool    `json:"can_viewer_reshare"`
	Caption          Caption `json:"caption"`
	CaptionIsEdited  bool    `json:"caption_is_edited"`
	Likes            int     `json:"like_count"`
	HasLiked         bool    `json:"has_liked"`
	// _TopLikers can be `string` or `[]string`.
	// Use TopLikers function instead of getting it directly.
	_TopLikers                   interface{} `json:"top_likers"`
	CommentLikesEnabled          bool        `json:"comment_likes_enabled"`
	CommentThreadingEnabled      bool        `json:"comment_threading_enabled"`
	HasMoreComments              bool        `json:"has_more_comments"`
	MaxNumVisiblePreviewComments int         `json:"max_num_visible_preview_comments"`
	// _PreviewComments can be `string` or `[]string`.
	// Use PreviewComments function instead of getting it directly.
	_PreviewComments     interface{} `json:"preview_comments,omitempty"`
	CommentCount         int         `json:"comment_count"`
	PhotoOfYou           bool        `json:"photo_of_you"`
	Usertags             Tag         `json:"usertags,omitempty"`
	FbUserTags           Tag         `json:"fb_user_tags"`
	CanViewerSave        bool        `json:"can_viewer_save"`
	OrganicTrackingToken string      `json:"organic_tracking_token"`
	Images               Images      `json:"image_versions2,omitempty"`
	OriginalWidth        int         `json:"original_width,omitempty"`
	OriginalHeight       int         `json:"original_height,omitempty"`
	ImportedTakenAt      int         `json:"imported_taken_at,omitempty"`

	// Only for stories
	StoryEvents              []interface{} `json:"story_events"`
	StoryHashtags            []interface{} `json:"story_hashtags"`
	StoryPolls               []interface{} `json:"story_polls"`
	StoryFeedMedia           []interface{} `json:"story_feed_media"`
	StorySoundOn             []interface{} `json:"story_sound_on"`
	CreativeConfig           interface{}   `json:"creative_config"`
	StoryLocations           []interface{} `json:"story_locations"`
	StorySliders             []interface{} `json:"story_sliders"`
	StoryQuestions           []interface{} `json:"story_questions"`
	StoryProductItems        []interface{} `json:"story_product_items"`
	SupportsReelReactions    bool          `json:"supports_reel_reactions"`
	ShowOneTapFbShareTooltip bool          `json:"show_one_tap_fb_share_tooltip"`
	HasSharedToFb            int           `json:"has_shared_to_fb"`
	Mentions                 []Mentions
	Videos                   []Videos `json:"video_versions,omitempty"`
	HasAudio                 bool     `json:"has_audio,omitempty"`
	VideoDuration            float64  `json:"video_duration,omitempty"`
	IsDashEligible           int      `json:"is_dash_eligible,omitempty"`
	VideoDashManifest        string   `json:"video_dash_manifest,omitempty"`
	NumberOfQualities        int      `json:"number_of_qualities,omitempty"`
}

// TopLikers returns string slice or single string (inside string slice)
// Depending on TopLikers parameter.
func (item *Item) TopLikers() []string {
	switch s := item._TopLikers.(type) {
	case string:
		return []string{s}
	case []string:
		return s
	}
	return nil
}

// PreviewComments returns string slice or single string (inside string slice)
// Depending on PreviewComments parameter.
func (item *Item) PreviewComments() []string {
	switch s := item._PreviewComments.(type) {
	case string:
		return []string{s}
	case []string:
		return s
	}
	return nil
}

type Media interface {
	Next() error
}

type StoryMedia struct {
	inst     *Instagram
	endpoint string
	uid      int64

	ID              int      `json:"id"`
	LatestReelMedia int      `json:"latest_reel_media"`
	ExpiringAt      int      `json:"expiring_at"`
	Seen            float64  `json:"seen"`
	CanReply        bool     `json:"can_reply"`
	CanReshare      bool     `json:"can_reshare"`
	ReelType        string   `json:"reel_type"`
	User            User     `json:"user"`
	Items           []Item   `json:"items"`
	ReelMentions    []string `json:"reel_mentions"`
	PrefetchCount   int      `json:"prefetch_count"`
	HasBestiesMedia bool     `json:"has_besties_media"`
	Status          string   `json:"status"`
}

// Next allows to paginate after calling:
// User.Stories
func (media *StoryMedia) Next() (err error) {
	var body []byte
	insta := media.inst
	endpoint := media.endpoint

	if media.uid != 0 {
		endpoint = fmt.Sprintf(endpoint, media.uid)
	}
	body, err = insta.sendSimpleRequest(endpoint)
	if err == nil {
		m := StoryMedia{}
		err = json.Unmarshal(body, &m)
		if err == nil {
			err = ErrNoMore
			*media = m
			media.inst = insta
			media.endpoint = endpoint
			// TODO check NextID media
		}
	}
	return err
}

// Media represent a set of media items
type FeedMedia struct {
	inst *Instagram

	uid      int64
	endpoint string

	Items               []Item `json:"items"`
	NumResults          int    `json:"num_results"`
	MoreAvailable       bool   `json:"more_available"`
	AutoLoadMoreEnabled bool   `json:"auto_load_more_enabled"`
	Status              string `json:"status"`
	// Can be int64 and string
	// this is why recomend Next() usage :')
	NextID interface{} `json:"next_max_id"`
}

// Next allows to paginate after calling:
// User.Feed
//
// returns ErrNoMore when list reach the end.
func (media *FeedMedia) Next() (err error) {
	var body []byte
	insta := media.inst
	endpoint := media.endpoint
	next := ""

	switch s := media.NextID.(type) {
	case string:
		next = s
	case int64:
		next = strconv.FormatInt(s, 10)
	}

	if media.uid != 0 {
		endpoint = fmt.Sprintf(endpoint, media.uid)
	}

	body, err = insta.sendRequest(
		&reqOptions{
			Endpoint: endpoint,
			Query: map[string]string{
				"max_id":         next,
				"rank_token":     insta.rankToken,
				"min_timestamp":  "",
				"ranked_content": "true",
			},
		},
	)
	if err == nil {
		m := FeedMedia{}
		err = json.Unmarshal(body, &m)
		if err == nil {
			*media = m
			media.inst = insta
			media.endpoint = endpoint
			if m.NextID == 0 || !m.MoreAvailable {
				err = ErrNoMore
			}
		}
	}
	return err
}
<|endoftext|>


<commit_before><commit_msg>cmd/gorename: log 'go build' output on failure<commit_after><|endoftext|>


<commit_before>// Copyright 2015 iquota Authors. All rights reserved.
// Use of this source code is governed by a BSD style
// license that can be found in the LICENSE file.

package main

import (
	"encoding/json"
	"net/http"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/context"
	"github.com/spf13/viper"
	"github.com/ubccr/iquota"
)

func errorHandler(app *Application, w http.ResponseWriter, status int, err *iquota.IsiError) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	if err != nil {
		out, err := json.Marshal(err)
		if err != nil {
			logrus.Printf("Error encoding error message as json: %s", err)
			return
		}
		w.Write(out)
	}
}

func IndexHandler(app *Application) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user := context.Get(r, "user").(*User)
		if user == nil {
			logrus.Error("index handler: user not found in request context")
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		quotas := make([]*iquota.Quota, 0)

		for _, q := range app.defaultUserQuota {
			quotas = append(quotas, q)
		}

		for _, q := range app.defaultGroupQuota {
			quotas = append(quotas, q)
		}

		out, err := json.Marshal(quotas)
		if err != nil {
			logrus.Printf("Error encoding data as json: %s", err)
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(out)
	})
}

func UserQuotaHandler(app *Application) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user := context.Get(r, "user").(*User)
		if user == nil {
			logrus.Error("user quota handler: user not found in request context")
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		qp := new(iquota.QuotaParams)
		app.decoder.Decode(qp, r.URL.Query())

		if len(qp.Path) == 0 {
			errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Path is required"})
			return
		}

		uid := user.Uid
		if len(qp.User) != 0 {
			if !user.IsAdmin() {
				errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Access denied"})
				return
			}

			uid = qp.User
		}

		var qres *iquota.QuotaResponse

		if viper.GetBool("enable_cache") {
			cqres, err := FetchUserQuotaCache(qp.Path, uid)
			if err == nil {
				qres = cqres
			}
		}

		if qres == nil {
			c := NewOnefsClient()
			res, err := c.FetchUserQuota(qp.Path, uid)
			if err != nil {
				logrus.WithFields(logrus.Fields{
					"err": err.Error(),
					"uid": uid,
				}).Error("Failed to fetch user quota")
				if ierr, ok := err.(*iquota.IsiError); ok {
					errorHandler(app, w, http.StatusBadRequest, ierr)
				} else {
					errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Fatal system error"})
				}

				return
			}

			qres = res

			if viper.GetBool("enable_cache") {
				SetUserQuotaCache(qp.Path, uid, qres)
			}
		}

		qr := &iquota.QuotaRestResponse{Quotas: qres.Quotas}
		qr.Default, _ = app.defaultUserQuota[qp.Path]

		out, err := json.Marshal(qr)
		if err != nil {
			logrus.Printf("Error encoding data as json: %s", err)
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(out)
	})
}

func GroupQuotaHandler(app *Application) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user := context.Get(r, "user").(*User)
		if user == nil {
			logrus.Error("group quota handler: user not found in request context")
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		qp := new(iquota.QuotaParams)
		app.decoder.Decode(qp, r.URL.Query())

		if len(qp.Path) == 0 {
			errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Path is required"})
			return
		}

		groups := user.Groups
		if len(qp.Group) != 0 {
			if !user.IsAdmin() {
				errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Access denied"})
				return
			}

			groups = []string{qp.Group}
		}

		c := NewOnefsClient()
		gquotas := make([]*iquota.Quota, 0)

		for _, group := range groups {

			var qres *iquota.QuotaResponse

			if viper.GetBool("enable_cache") {
				cqres, err := FetchGroupQuotaCache(qp.Path, group)
				if err != nil {
					if ierr, ok := err.(*iquota.IsiError); ok {
						if ierr.Code == "AEC_NOT_FOUND" && len(qp.Group) == 0 {
							continue
						}
						logrus.WithFields(logrus.Fields{
							"err":   ierr.Error(),
							"group": group,
						}).Error("Failed to fetch group quota")
						errorHandler(app, w, http.StatusBadRequest, ierr)
						return
					}
				}

				qres = cqres
			}

			if qres == nil {
				res, err := c.FetchGroupQuota(qp.Path, group)
				if err != nil {
					if ierr, ok := err.(*iquota.IsiError); ok {
						if ierr.Code == "AEC_NOT_FOUND" && viper.GetBool("enable_cache") {
							SetGroupNegCache(qp.Path, group)
						}

						if ierr.Code == "AEC_NOT_FOUND" && len(qp.Group) == 0 {
							continue
						}
						logrus.WithFields(logrus.Fields{
							"err":   ierr.Error(),
							"group": group,
						}).Error("Failed to fetch group quota")
						errorHandler(app, w, http.StatusBadRequest, ierr)
					} else {
						logrus.WithFields(logrus.Fields{
							"err":   err.Error(),
							"group": group,
						}).Error("Failed to fetch group quota")
						errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Fatal system error"})
					}

					return
				}

				qres = res
				if viper.GetBool("enable_cache") {
					SetGroupQuotaCache(qp.Path, group, qres)
				}
			}

			gquotas = append(gquotas, qres.Quotas...)
		}

		qr := &iquota.QuotaRestResponse{Quotas: gquotas}
		qr.Default, _ = app.defaultGroupQuota[qp.Path]

		out, err := json.Marshal(qr)
		if err != nil {
			logrus.Printf("Error encoding data as json: %s", err)
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(out)
	})
}
<commit_msg>Fix bug in user filter check<commit_after>// Copyright 2015 iquota Authors. All rights reserved.
// Use of this source code is governed by a BSD style
// license that can be found in the LICENSE file.

package main

import (
	"encoding/json"
	"net/http"

	"github.com/Sirupsen/logrus"
	"github.com/gorilla/context"
	"github.com/spf13/viper"
	"github.com/ubccr/iquota"
)

func errorHandler(app *Application, w http.ResponseWriter, status int, err *iquota.IsiError) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	if err != nil {
		out, err := json.Marshal(err)
		if err != nil {
			logrus.Printf("Error encoding error message as json: %s", err)
			return
		}
		w.Write(out)
	}
}

func IndexHandler(app *Application) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user := context.Get(r, "user").(*User)
		if user == nil {
			logrus.Error("index handler: user not found in request context")
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		quotas := make([]*iquota.Quota, 0)

		for _, q := range app.defaultUserQuota {
			quotas = append(quotas, q)
		}

		for _, q := range app.defaultGroupQuota {
			quotas = append(quotas, q)
		}

		out, err := json.Marshal(quotas)
		if err != nil {
			logrus.Printf("Error encoding data as json: %s", err)
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(out)
	})
}

func UserQuotaHandler(app *Application) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user := context.Get(r, "user").(*User)
		if user == nil {
			logrus.Error("user quota handler: user not found in request context")
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		qp := new(iquota.QuotaParams)
		app.decoder.Decode(qp, r.URL.Query())

		if len(qp.Path) == 0 {
			errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Path is required"})
			return
		}

		uid := user.Uid
		if len(qp.User) != 0 && qp.User != uid {
			if !user.IsAdmin() {
				errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Access denied"})
				return
			}

			uid = qp.User
		}

		var qres *iquota.QuotaResponse

		if viper.GetBool("enable_cache") {
			cqres, err := FetchUserQuotaCache(qp.Path, uid)
			if err == nil {
				qres = cqres
			}
		}

		if qres == nil {
			c := NewOnefsClient()
			res, err := c.FetchUserQuota(qp.Path, uid)
			if err != nil {
				logrus.WithFields(logrus.Fields{
					"err": err.Error(),
					"uid": uid,
				}).Error("Failed to fetch user quota")
				if ierr, ok := err.(*iquota.IsiError); ok {
					errorHandler(app, w, http.StatusBadRequest, ierr)
				} else {
					errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Fatal system error"})
				}

				return
			}

			qres = res

			if viper.GetBool("enable_cache") {
				SetUserQuotaCache(qp.Path, uid, qres)
			}
		}

		qr := &iquota.QuotaRestResponse{Quotas: qres.Quotas}
		qr.Default, _ = app.defaultUserQuota[qp.Path]

		out, err := json.Marshal(qr)
		if err != nil {
			logrus.Printf("Error encoding data as json: %s", err)
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(out)
	})
}

func GroupQuotaHandler(app *Application) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		user := context.Get(r, "user").(*User)
		if user == nil {
			logrus.Error("group quota handler: user not found in request context")
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		qp := new(iquota.QuotaParams)
		app.decoder.Decode(qp, r.URL.Query())

		if len(qp.Path) == 0 {
			errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Path is required"})
			return
		}

		groups := user.Groups
		if len(qp.Group) != 0 {
			if !user.IsAdmin() {
				errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Access denied"})
				return
			}

			groups = []string{qp.Group}
		}

		c := NewOnefsClient()
		gquotas := make([]*iquota.Quota, 0)

		for _, group := range groups {

			var qres *iquota.QuotaResponse

			if viper.GetBool("enable_cache") {
				cqres, err := FetchGroupQuotaCache(qp.Path, group)
				if err != nil {
					if ierr, ok := err.(*iquota.IsiError); ok {
						if ierr.Code == "AEC_NOT_FOUND" && len(qp.Group) == 0 {
							continue
						}
						logrus.WithFields(logrus.Fields{
							"err":   ierr.Error(),
							"group": group,
						}).Error("Failed to fetch group quota")
						errorHandler(app, w, http.StatusBadRequest, ierr)
						return
					}
				}

				qres = cqres
			}

			if qres == nil {
				res, err := c.FetchGroupQuota(qp.Path, group)
				if err != nil {
					if ierr, ok := err.(*iquota.IsiError); ok {
						if ierr.Code == "AEC_NOT_FOUND" && viper.GetBool("enable_cache") {
							SetGroupNegCache(qp.Path, group)
						}

						if ierr.Code == "AEC_NOT_FOUND" && len(qp.Group) == 0 {
							continue
						}
						logrus.WithFields(logrus.Fields{
							"err":   ierr.Error(),
							"group": group,
						}).Error("Failed to fetch group quota")
						errorHandler(app, w, http.StatusBadRequest, ierr)
					} else {
						logrus.WithFields(logrus.Fields{
							"err":   err.Error(),
							"group": group,
						}).Error("Failed to fetch group quota")
						errorHandler(app, w, http.StatusBadRequest, &iquota.IsiError{Code: "AEC_BAD_REQUEST", Message: "Fatal system error"})
					}

					return
				}

				qres = res
				if viper.GetBool("enable_cache") {
					SetGroupQuotaCache(qp.Path, group, qres)
				}
			}

			gquotas = append(gquotas, qres.Quotas...)
		}

		qr := &iquota.QuotaRestResponse{Quotas: gquotas}
		qr.Default, _ = app.defaultGroupQuota[qp.Path]

		out, err := json.Marshal(qr)
		if err != nil {
			logrus.Printf("Error encoding data as json: %s", err)
			errorHandler(app, w, http.StatusInternalServerError, nil)
			return
		}

		w.Header().Set("Content-Type", "application/json")
		w.Write(out)
	})
}
<|endoftext|>


<commit_before>package main

import (
	"strconv"

	"github.com/shirou/gopsutil/cpu"
)

// `cpuinfo` represent the CPU informations
type cpuinfo struct {
	count     string // number of CPUs
	vendorID  string // vendor name ex. AuthenticAMD, GenuineIntel
	modelName string // CPU model name
	cpuMhz    string //
	//TODO temperature and fan speed ?
}

// Get informations about the cpu by using `gopesutil` packages
func getCPUinfo() cpuinfo {
	info, err := cpu.Info() // cpu.Info() return a slice of InfoStat structs
	if err != nil {
		panic(err) //TODO do not panic but manage the error
	}

	result := cpuinfo{
		count:     strconv.Itoa(len(info)),
		vendorID:  info[0].VendorID, //BUG in `gopsutil`
		modelName: info[0].ModelName,
		cpuMhz:    strconv.FormatFloat(info[0].Mhz, 'f', 0, 64),
	}
	return result
}

//TODO count cores ?
//TODO count the physicals id = multiples sockets

//TODO We need to improve this. For now it take vendorID, modelName, etc from
//the first CPU assuming than all CPUs are the same (probably OK)and than there
//is only one socket (not true on servers)
//
// http://superuser.com/questions/388115/interpreting-output-of-cat-proc-cpuinfo
// http://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo
//
// TODO add temperature
<commit_msg>Update cpusinfo stats<commit_after>package main

import (
	"strconv"
	"time"

	"github.com/shirou/gopsutil/cpu"
)

// `cpuinfo` represent the CPU informations
type cpuinfo struct {
	count     string // number of CPUs
	vendorID  string // vendor name ex. AuthenticAMD, GenuineIntel
	modelName string // CPU model name
	cpuMhz    string // speed of the CPU
	//TODO temperature and fan speed ?
}

// Get informations about the cpu by using `gopesutil` packages
func getCPUinfo() cpuinfo {
	info, err := cpu.Info() // cpu.Info() return a slice of InfoStat structs
	if err != nil {
		panic(err) //TODO do not panic but manage the error
	}

	result := cpuinfo{
		count:     strconv.Itoa(len(info)),
		vendorID:  info[0].VendorID, //BUG in `gopsutil`
		modelName: info[0].ModelName,
		cpuMhz:    strconv.FormatFloat(info[0].Mhz, 'f', 0, 64),
	}
	return result
}

// get the system-wide CPU utilization percentage
func getCPUpercent() (usedPercent int) {
	percent, err := cpu.Percent((500 * time.Millisecond), false) // 0.5 seconds, `false` for system wide
	if err != nil {
		panic(err) //TODO do not panic but manage the error
	}

	return int(percent[0]) // even if cpu.Percent() use `false` it return a slice
}

//TODO count cores ?
//TODO count the physicals id = multiples sockets

//TODO We need to improve this. For now it take vendorID, modelName, etc from
//the first CPU assuming than all CPUs are the same (probably OK)and than there
//is only one socket (not true on servers)
//
// http://superuser.com/questions/388115/interpreting-output-of-cat-proc-cpuinfo
// http://unix.stackexchange.com/questions/146051/number-of-processors-in-proc-cpuinfo
//
// TODO add temperature
<|endoftext|>


<commit_before>package token

import (
	"fmt"
)

type Token struct {
	Typ TokenType
	Val string
	Pos int
}

func NewToken(typ TokenType, val string, pos int) Token {
	return Token{typ, val, pos};
}

const IgnoreTokenPos = -1

func (t *Token) Compare(o Token) bool{
	if (t.Pos == IgnoreTokenPos || o.Pos == IgnoreTokenPos) {
		return t.Typ == o.Typ && t.Val == o.Val;
	}
	return t.Typ == o.Typ && t.Val == o.Val && t.Pos == o.Pos;
}

func (i *Token) String() string {
	switch i.Typ {
	case EOF:
		return "EOF"
	}
	val := i.Val
	if len(val) > 10 {
		//val = fmt.Sprintf("%.10q...", val)
	}
	return fmt.Sprintf("Token(%v, %q, %d)", i.Typ, val, i.Pos)
}

type TokenType string

const (
	EOF TokenType	= "eof"
	ERROR 		= "error"

	USINGDATABASE 	= "usingDatabase"
	FORDOMAIN 	= "forDomain"
	INCONTEXT 	= "inContext"
	WITHINAGGREGATE = "withinAggregate"

	CLASSOPEN 	= "<|"
	CLASSCLOSE 	= "|>"
	OBJECTNAME 	= "objectName"

	//DQL Keywords - Objects
	CREATE 	   = "create"
	LIST	   = "list"
	DATABASE   = "database"
	DATABASES   = "databases"
	DOMAIN     = "domain"
	CONTEXT    = "context"
	AGGREGATE  = "aggregate"
	VALUE      = "value"
	EVENT      = "event"
	ENTITY     = "entity"
	COMMAND    = "command"
	PROJECTION = "projection"
	INVARIANT  = "invariant"
	QUERY      = "query"
	AS 	   = "as"
	ON 	   = "on"

	// Class components
	PROPERTIES = "properties"
	CHECK      = "check"
	HANDLER    = "handler"
	FUNCTION   = "function"
	WHENEVENT  = "when event"

	// Command Handler statements
	ASSERTINVARIANT = "assert invariant"
	NOT 		= "not"
	RUNQUERY 	= "run query"
	APPLYEVENT 	= "apply event"

	// Operators
	ASSIGN    = "="
	PLUS      = "+"
	MINUS     = "-"
	BANG      = "!"
	ASTERISK  = "*"
	SLASH     = "/"
	REMAINDER = "%"
	ARROW 	  = "->"
	STRONGARROW = "=>"
	AND 	  = "and"
	OR 	  = "or"
	LT 	  = "<"
	GT 	  = ">"
	EQ 	  = "=="
	NOTEQ	  = "!="
	LTOREQ 	  = "<="
	GTOREQ 	  = ">="

	// Delimiters
	COMMA    = ","
	SEMICOLON= ";"
	COLON    = ":"
	LPAREN   = "("
	RPAREN   = ")"
	LBRACE   = "{"
	RBRACE   = "}"
	LBRACKET = "["
	RBRACKET = "]"

	//Types
	INTEGER	= "integer"
	FLOAT   = "float"
	BOOLEAN = "boolean"
	STRING  = "string"
	NULL    = "null"
	IDENT 	= "identifier"

	//Statements
	IF 	= "if"
	ELSEIF 	= "else if"
	ELSE 	= "else"
	RETURN 	= "return"
	FOREACH = "foreach"
)

func Semicolon(pos int) Token {
	return NewToken(SEMICOLON, ";", pos);
}

func ClsOpen(pos int) Token {
	return NewToken(CLASSOPEN, "<|", pos);
}

func ClsClose(pos int) Token {
	return NewToken(CLASSCLOSE, "|>", pos);
}<commit_msg>Removed commented out line<commit_after>package token

import (
	"fmt"
)

type Token struct {
	Typ TokenType
	Val string
	Pos int
}

func NewToken(typ TokenType, val string, pos int) Token {
	return Token{typ, val, pos};
}

const IgnoreTokenPos = -1

func (t *Token) Compare(o Token) bool{
	if (t.Pos == IgnoreTokenPos || o.Pos == IgnoreTokenPos) {
		return t.Typ == o.Typ && t.Val == o.Val;
	}
	return t.Typ == o.Typ && t.Val == o.Val && t.Pos == o.Pos;
}

func (i *Token) String() string {
	switch i.Typ {
	case EOF:
		return "EOF"
	}
	val := i.Val

	return fmt.Sprintf("Token(%v, %q, %d)", i.Typ, val, i.Pos)
}

type TokenType string

const (
	EOF TokenType	= "eof"
	ERROR 		= "error"

	USINGDATABASE 	= "usingDatabase"
	FORDOMAIN 	= "forDomain"
	INCONTEXT 	= "inContext"
	WITHINAGGREGATE = "withinAggregate"

	CLASSOPEN 	= "<|"
	CLASSCLOSE 	= "|>"
	OBJECTNAME 	= "objectName"

	//DQL Keywords - Objects
	CREATE 	   = "create"
	LIST	   = "list"
	DATABASE   = "database"
	DATABASES   = "databases"
	DOMAIN     = "domain"
	CONTEXT    = "context"
	AGGREGATE  = "aggregate"
	VALUE      = "value"
	EVENT      = "event"
	ENTITY     = "entity"
	COMMAND    = "command"
	PROJECTION = "projection"
	INVARIANT  = "invariant"
	QUERY      = "query"
	AS 	   = "as"
	ON 	   = "on"

	// Class components
	PROPERTIES = "properties"
	CHECK      = "check"
	HANDLER    = "handler"
	FUNCTION   = "function"
	WHENEVENT  = "when event"

	// Command Handler statements
	ASSERTINVARIANT = "assert invariant"
	NOT 		= "not"
	RUNQUERY 	= "run query"
	APPLYEVENT 	= "apply event"

	// Operators
	ASSIGN    = "="
	PLUS      = "+"
	MINUS     = "-"
	BANG      = "!"
	ASTERISK  = "*"
	SLASH     = "/"
	REMAINDER = "%"
	ARROW 	  = "->"
	STRONGARROW = "=>"
	AND 	  = "and"
	OR 	  = "or"
	LT 	  = "<"
	GT 	  = ">"
	EQ 	  = "=="
	NOTEQ	  = "!="
	LTOREQ 	  = "<="
	GTOREQ 	  = ">="

	// Delimiters
	COMMA    = ","
	SEMICOLON= ";"
	COLON    = ":"
	LPAREN   = "("
	RPAREN   = ")"
	LBRACE   = "{"
	RBRACE   = "}"
	LBRACKET = "["
	RBRACKET = "]"

	//Types
	INTEGER	= "integer"
	FLOAT   = "float"
	BOOLEAN = "boolean"
	STRING  = "string"
	NULL    = "null"
	IDENT 	= "identifier"

	//Statements
	IF 	= "if"
	ELSEIF 	= "else if"
	ELSE 	= "else"
	RETURN 	= "return"
	FOREACH = "foreach"
)

func Semicolon(pos int) Token {
	return NewToken(SEMICOLON, ";", pos);
}

func ClsOpen(pos int) Token {
	return NewToken(CLASSOPEN, "<|", pos);
}

func ClsClose(pos int) Token {
	return NewToken(CLASSCLOSE, "|>", pos);
}<|endoftext|>


<commit_before>package files

import (
	"io"
	"net/http"
	"strings"
	"testing"
	"time"

	"github.com/cozy/cozy-stack/pkg/permissions"
	"github.com/labstack/echo"
	"github.com/stretchr/testify/assert"
)

func TestCreateDirNoToken(t *testing.T) {
	noToken := ""
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", noToken, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 401, res.StatusCode)
}

func TestCreateDirBadType(t *testing.T) {
	badtok, _ := testInstance.MakeJWT(permissions.AccessTokenAudience, "io.cozy.events", clientID, time.Now())
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", badtok, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 403, res.StatusCode)
}

func TestCreateDirLimitedScope(t *testing.T) {
	res, data := createDir(t, "/files/?Name=permissionholder&Type=directory")
	assert.Equal(t, 201, res.StatusCode)
	id := data["data"].(map[string]interface{})["id"].(string)
	badtok, _ := testInstance.MakeJWT(permissions.AccessTokenAudience, "io.cozy.files:ALL:"+id, clientID, time.Now())

	// not in authorized dir
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", badtok, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 403, res.StatusCode)

	// in authorized dir
	res2, err := request("POST", "/files/"+id+"?Name=icancreateyou&Type=directory", token, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 201, res2.StatusCode)
}

func TestCreateDirBadVerb(t *testing.T) {
	badtok, _ := testInstance.MakeJWT(permissions.AccessTokenAudience, "io.cozy.files:GET", clientID, time.Now())
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", badtok, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 403, res.StatusCode)
}

func request(m, path, token string, body io.Reader) (*http.Response, error) {
	req, err := http.NewRequest(m, ts.URL+path, body)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-Type", "text/plain")
	if token != "" {
		req.Header.Add(echo.HeaderAuthorization, "Bearer "+token)
	}
	return http.DefaultClient.Do(req)
}
<commit_msg>fix web/files test<commit_after>package files

import (
	"io"
	"net/http"
	"strings"
	"testing"
	"time"

	"github.com/cozy/cozy-stack/pkg/permissions"
	"github.com/labstack/echo"
	"github.com/stretchr/testify/assert"
)

func TestCreateDirNoToken(t *testing.T) {
	noToken := ""
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", noToken, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 401, res.StatusCode)
}

func TestCreateDirBadType(t *testing.T) {
	badtok, _ := testInstance.MakeJWT(permissions.AccessTokenAudience, clientID, "io.cozy.events", time.Now())
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", badtok, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 403, res.StatusCode)
}

func TestCreateDirLimitedScope(t *testing.T) {
	res, data := createDir(t, "/files/?Name=permissionholder&Type=directory")
	assert.Equal(t, 201, res.StatusCode)
	id := data["data"].(map[string]interface{})["id"].(string)
	badtok, _ := testInstance.MakeJWT(permissions.AccessTokenAudience, clientID, "io.cozy.files:ALL:"+id, time.Now())

	// not in authorized dir
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", badtok, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 403, res.StatusCode)

	// in authorized dir
	res2, err := request("POST", "/files/"+id+"?Name=icancreateyou&Type=directory", token, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 201, res2.StatusCode)
}

func TestCreateDirBadVerb(t *testing.T) {
	badtok, _ := testInstance.MakeJWT(permissions.AccessTokenAudience, clientID, "io.cozy.files:GET", time.Now())
	res, err := request("POST", "/files/?Name=icantcreateyou&Type=directory", badtok, strings.NewReader(""))
	assert.NoError(t, err)
	assert.Equal(t, 403, res.StatusCode)
}

func request(m, path, token string, body io.Reader) (*http.Response, error) {
	req, err := http.NewRequest(m, ts.URL+path, body)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-Type", "text/plain")
	if token != "" {
		req.Header.Add(echo.HeaderAuthorization, "Bearer "+token)
	}
	return http.DefaultClient.Do(req)
}
<|endoftext|>


<commit_before>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// The worker/uniter/jujuc package implements the server side of the jujuc proxy
// tool, which forwards command invocations to the unit agent process so that
// they can be executed against specific state.
package jujuc

import (
	"bytes"
	"fmt"
	"net"
	"net/rpc"
	"path/filepath"
	"sort"
	"sync"

	"github.com/juju/cmd"
	"github.com/juju/loggo"
	"github.com/juju/utils/exec"

	// "github.com/juju/juju/juju/osenv"
)

var logger = loggo.GetLogger("worker.uniter.jujuc")

// newCommands maps Command names to initializers.
var newCommands = map[string]func(Context) cmd.Command{
	"close-port":    NewClosePortCommand,
	"config-get":    NewConfigGetCommand,
	"juju-log":      NewJujuLogCommand,
	"open-port":     NewOpenPortCommand,
	"relation-get":  NewRelationGetCommand,
	"relation-ids":  NewRelationIdsCommand,
	"relation-list": NewRelationListCommand,
	"relation-set":  NewRelationSetCommand,
	"unit-get":      NewUnitGetCommand,
	"owner-get":     NewOwnerGetCommand,
}

// CommandNames returns the names of all jujuc commands.
func CommandNames() (names []string) {
	for name := range newCommands {
		names = append(names, name)
	}
	sort.Strings(names)
	return
}

// NewCommand returns an instance of the named Command, initialized to execute
// against the supplied Context.
func NewCommand(ctx Context, name string) (cmd.Command, error) {
	f := newCommands[name]
	if f == nil {
		return nil, fmt.Errorf("unknown command: %s", name)
	}
	return f(ctx), nil
}

// Request contains the information necessary to run a Command remotely.
type Request struct {
	ContextId   string
	Dir         string
	CommandName string
	Args        []string
}

// CmdGetter looks up a Command implementation connected to a particular Context.
type CmdGetter func(contextId, cmdName string) (cmd.Command, error)

// Jujuc implements the jujuc command in the form required by net/rpc.
type Jujuc struct {
	mu     sync.Mutex
	getCmd CmdGetter
}

// badReqErrorf returns an error indicating a bad Request.
func badReqErrorf(format string, v ...interface{}) error {
	return fmt.Errorf("bad request: "+format, v...)
}

// Main runs the Command specified by req, and fills in resp. A single command
// is run at a time.
func (j *Jujuc) Main(req Request, resp *exec.ExecResponse) error {
	if req.CommandName == "" {
		return badReqErrorf("command not specified")
	}
	if !filepath.IsAbs(req.Dir) {
		return badReqErrorf("Dir is not absolute")
	}
	c, err := j.getCmd(req.ContextId, req.CommandName)
	if err != nil {
		return badReqErrorf("%s", err)
	}
	var stdin, stdout, stderr bytes.Buffer
	ctx := &cmd.Context{
		Dir:    req.Dir,
		Stdin:  &stdin,
		Stdout: &stdout,
		Stderr: &stderr,
	}
	j.mu.Lock()
	defer j.mu.Unlock()
	logger.Infof("running hook tool %q %q", req.CommandName, req.Args)
	logger.Debugf("hook context id %q; dir %q", req.ContextId, req.Dir)
	resp.Code = cmd.Main(c, ctx, req.Args)
	resp.Stdout = stdout.Bytes()
	resp.Stderr = stderr.Bytes()
	return nil
}

// Server implements a server that serves command invocations via
// a unix domain socket.
type Server struct {
	socketPath string
	listener   net.Listener
	server     *rpc.Server
	closed     chan bool
	closing    chan bool
	wg         sync.WaitGroup
}

// NewServer creates an RPC server bound to socketPath, which can execute
// remote command invocations against an appropriate Context. It will not
// actually do so until Run is called.
func NewServer(getCmd CmdGetter, socketPath string) (*Server, error) {
	server := rpc.NewServer()
	if err := server.Register(&Jujuc{getCmd: getCmd}); err != nil {
		return nil, err
	}
	listener, err := net.Listen("unix", socketPath)
	if err != nil {
		return nil, err
	}
	s := &Server{
		socketPath: socketPath,
		listener:   listener,
		server:     server,
		closed:     make(chan bool),
		closing:    make(chan bool),
	}
	return s, nil
}

// Run accepts new connections until it encounters an error, or until Close is
// called, and then blocks until all existing connections have been closed.
func (s *Server) Run() (err error) {
	var conn net.Conn
	for {
		conn, err = s.listener.Accept()
		if err != nil {
			break
		}
		s.wg.Add(1)
		go func(conn net.Conn) {
			s.server.ServeConn(conn)
			s.wg.Done()
		}(conn)
	}
	select {
	case <-s.closing:
		// Someone has called Close(), so it is overwhelmingly likely that
		// the error from Accept is a direct result of the Listener being
		// closed, and can therefore be safely ignored.
		err = nil
	default:
	}
	s.wg.Wait()
	close(s.closed)
	return
}

// Close immediately stops accepting connections, and blocks until all existing
// connections have been closed.
func (s *Server) Close() {
	close(s.closing)
	s.listener.Close()
	<-s.closed
}
<commit_msg>removed commented import<commit_after>// Copyright 2012, 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

// The worker/uniter/jujuc package implements the server side of the jujuc proxy
// tool, which forwards command invocations to the unit agent process so that
// they can be executed against specific state.
package jujuc

import (
	"bytes"
	"fmt"
	"net"
	"net/rpc"
	"path/filepath"
	"sort"
	"sync"

	"github.com/juju/cmd"
	"github.com/juju/loggo"
	"github.com/juju/utils/exec"
)

var logger = loggo.GetLogger("worker.uniter.jujuc")

// newCommands maps Command names to initializers.
var newCommands = map[string]func(Context) cmd.Command{
	"close-port":    NewClosePortCommand,
	"config-get":    NewConfigGetCommand,
	"juju-log":      NewJujuLogCommand,
	"open-port":     NewOpenPortCommand,
	"relation-get":  NewRelationGetCommand,
	"relation-ids":  NewRelationIdsCommand,
	"relation-list": NewRelationListCommand,
	"relation-set":  NewRelationSetCommand,
	"unit-get":      NewUnitGetCommand,
	"owner-get":     NewOwnerGetCommand,
}

// CommandNames returns the names of all jujuc commands.
func CommandNames() (names []string) {
	for name := range newCommands {
		names = append(names, name)
	}
	sort.Strings(names)
	return
}

// NewCommand returns an instance of the named Command, initialized to execute
// against the supplied Context.
func NewCommand(ctx Context, name string) (cmd.Command, error) {
	f := newCommands[name]
	if f == nil {
		return nil, fmt.Errorf("unknown command: %s", name)
	}
	return f(ctx), nil
}

// Request contains the information necessary to run a Command remotely.
type Request struct {
	ContextId   string
	Dir         string
	CommandName string
	Args        []string
}

// CmdGetter looks up a Command implementation connected to a particular Context.
type CmdGetter func(contextId, cmdName string) (cmd.Command, error)

// Jujuc implements the jujuc command in the form required by net/rpc.
type Jujuc struct {
	mu     sync.Mutex
	getCmd CmdGetter
}

// badReqErrorf returns an error indicating a bad Request.
func badReqErrorf(format string, v ...interface{}) error {
	return fmt.Errorf("bad request: "+format, v...)
}

// Main runs the Command specified by req, and fills in resp. A single command
// is run at a time.
func (j *Jujuc) Main(req Request, resp *exec.ExecResponse) error {
	if req.CommandName == "" {
		return badReqErrorf("command not specified")
	}
	if !filepath.IsAbs(req.Dir) {
		return badReqErrorf("Dir is not absolute")
	}
	c, err := j.getCmd(req.ContextId, req.CommandName)
	if err != nil {
		return badReqErrorf("%s", err)
	}
	var stdin, stdout, stderr bytes.Buffer
	ctx := &cmd.Context{
		Dir:    req.Dir,
		Stdin:  &stdin,
		Stdout: &stdout,
		Stderr: &stderr,
	}
	j.mu.Lock()
	defer j.mu.Unlock()
	logger.Infof("running hook tool %q %q", req.CommandName, req.Args)
	logger.Debugf("hook context id %q; dir %q", req.ContextId, req.Dir)
	resp.Code = cmd.Main(c, ctx, req.Args)
	resp.Stdout = stdout.Bytes()
	resp.Stderr = stderr.Bytes()
	return nil
}

// Server implements a server that serves command invocations via
// a unix domain socket.
type Server struct {
	socketPath string
	listener   net.Listener
	server     *rpc.Server
	closed     chan bool
	closing    chan bool
	wg         sync.WaitGroup
}

// NewServer creates an RPC server bound to socketPath, which can execute
// remote command invocations against an appropriate Context. It will not
// actually do so until Run is called.
func NewServer(getCmd CmdGetter, socketPath string) (*Server, error) {
	server := rpc.NewServer()
	if err := server.Register(&Jujuc{getCmd: getCmd}); err != nil {
		return nil, err
	}
	listener, err := net.Listen("unix", socketPath)
	if err != nil {
		return nil, err
	}
	s := &Server{
		socketPath: socketPath,
		listener:   listener,
		server:     server,
		closed:     make(chan bool),
		closing:    make(chan bool),
	}
	return s, nil
}

// Run accepts new connections until it encounters an error, or until Close is
// called, and then blocks until all existing connections have been closed.
func (s *Server) Run() (err error) {
	var conn net.Conn
	for {
		conn, err = s.listener.Accept()
		if err != nil {
			break
		}
		s.wg.Add(1)
		go func(conn net.Conn) {
			s.server.ServeConn(conn)
			s.wg.Done()
		}(conn)
	}
	select {
	case <-s.closing:
		// Someone has called Close(), so it is overwhelmingly likely that
		// the error from Accept is a direct result of the Listener being
		// closed, and can therefore be safely ignored.
		err = nil
	default:
	}
	s.wg.Wait()
	close(s.closed)
	return
}

// Close immediately stops accepting connections, and blocks until all existing
// connections have been closed.
func (s *Server) Close() {
	close(s.closing)
	s.listener.Close()
	<-s.closed
}
<|endoftext|>


<commit_before><commit_msg>type names don't imply the resource mode<commit_after><|endoftext|>


<commit_before><commit_msg>Fix FSCK for VFS Swift layout v2 (#2527)<commit_after><|endoftext|>


<commit_before><commit_msg>Renamed SortWeightedData to SortWeighted<commit_after><|endoftext|>


<commit_before><commit_msg>subs uses the interface Project<commit_after><|endoftext|>


<commit_before><commit_msg>fixing byte array and binary string confusion.<commit_after><|endoftext|>