<commit_before>package printer

import (
	"strconv"

	"github.com/davyxu/tabtoy/exportorv2/i18n"
	"github.com/davyxu/tabtoy/exportorv2/model"
	"github.com/davyxu/tabtoy/util"
)

func valueWrapperJson(t model.FieldType, node *model.Node) string {

	switch t {
	case model.FieldType_String:
		return util.StringEscape(node.Value)
	case model.FieldType_Enum:
		return strconv.Itoa(int(node.EnumValue))
	}

	return node.Value
}

type jsonPrinter struct {
}

func (self *jsonPrinter) Run(g *Globals) *BinaryFile {

	bf := NewBinaryFile()
	bf.Printf("{\n")

	bf.Printf("	\"Tool\": \"github.com/davyxu/tabtoy\",\n")
	bf.Printf("	\"Version\": \"%s\",\n", g.Version)

	for tabIndex, tab := range g.Tables {

		if !tab.LocalFD.MatchTag(".json") {
			log.Infof("%s: %s", i18n.String(i18n.Printer_IgnoredByOutputTag), tab.Name())
			continue
		}

		if !printTableJson(bf, tab) {
			return nil
		}

		// 根字段分割
		if tabIndex < len(g.Tables)-1 {
			bf.Printf(", ")
		}

		bf.Printf("\n")
	}

	bf.Printf("}")

	return bf
}

func printTableJson(bf *BinaryFile, tab *model.Table) bool {

	bf.Printf("	\"%s\":[\n", tab.LocalFD.Name)

	// 遍历每一行
	for rIndex, r := range tab.Recs {

		bf.Printf("		{ ")

		// 遍历每一列
		for rootFieldIndex, node := range r.Nodes {

			if node.IsRepeated {
				bf.Printf("\"%s\":[ ", node.Name)
			} else {
				bf.Printf("\"%s\": ", node.Name)
			}

			// 普通值
			if node.Type != model.FieldType_Struct {

				if node.IsRepeated {

					// repeated 值序列
					for arrIndex, valueNode := range node.Child {

						bf.Printf("%s", valueWrapperJson(node.Type, valueNode))

						// 多个值分割
						if arrIndex < len(node.Child)-1 {
							bf.Printf(", ")
						}

					}
				} else {
					// 单值
					valueNode := node.Child[0]

					bf.Printf("%s", valueWrapperJson(node.Type, valueNode))

				}

			} else {

				// 遍历repeated的结构体
				for structIndex, structNode := range node.Child {

					// 结构体开始
					bf.Printf("{ ")

					// 遍历一个结构体的字段
					for structFieldIndex, fieldNode := range structNode.Child {

						// 值节点总是在第一个
						valueNode := fieldNode.Child[0]

						bf.Printf("\"%s\": %s", fieldNode.Name, valueWrapperJson(fieldNode.Type, valueNode))

						// 结构体字段分割
						if structFieldIndex < len(structNode.Child)-1 {
							bf.Printf(", ")
						}

					}

					// 结构体结束
					bf.Printf(" }")

					// 多个结构体分割
					if structIndex < len(node.Child)-1 {
						bf.Printf(", ")
					}

				}

			}

			if node.IsRepeated {
				bf.Printf(" ]")
			}

			// 根字段分割
			if rootFieldIndex < len(r.Nodes)-1 {
				bf.Printf(", ")
			}

		}

		bf.Printf(" }")

		if rIndex < len(tab.Recs)-1 {
			bf.Printf(",")
		}

		bf.Printf("\n")

	}

	bf.Printf("	]")

	return true

}

func init() {

	RegisterPrinter("json", &jsonPrinter{})

}
<commit_msg>修复: 忽略tag导致的json格式错误<commit_after>package printer

import (
	"strconv"

	"github.com/davyxu/tabtoy/exportorv2/i18n"
	"github.com/davyxu/tabtoy/exportorv2/model"
	"github.com/davyxu/tabtoy/util"
)

func valueWrapperJson(t model.FieldType, node *model.Node) string {

	switch t {
	case model.FieldType_String:
		return util.StringEscape(node.Value)
	case model.FieldType_Enum:
		return strconv.Itoa(int(node.EnumValue))
	}

	return node.Value
}

type jsonPrinter struct {
}

func (self *jsonPrinter) Run(g *Globals) *BinaryFile {

	bf := NewBinaryFile()
	bf.Printf("{\n")

	bf.Printf("	\"Tool\": \"github.com/davyxu/tabtoy\",\n")
	bf.Printf("	\"Version\": \"%s\",\n", g.Version)

	for tabIndex, tab := range g.Tables {

		if !tab.LocalFD.MatchTag(".json") {
			log.Infof("%s: %s", i18n.String(i18n.Printer_IgnoredByOutputTag), tab.Name())
			continue
		}

		if tabIndex > 0 {
			bf.Printf(", \n")
		}

		if !printTableJson(bf, tab) {
			return nil
		}

	}

	bf.Printf("}")

	return bf
}

func printTableJson(bf *BinaryFile, tab *model.Table) bool {

	bf.Printf("	\"%s\":[\n", tab.LocalFD.Name)

	// 遍历每一行
	for rIndex, r := range tab.Recs {

		bf.Printf("		{ ")

		// 遍历每一列
		for rootFieldIndex, node := range r.Nodes {

			if node.IsRepeated {
				bf.Printf("\"%s\":[ ", node.Name)
			} else {
				bf.Printf("\"%s\": ", node.Name)
			}

			// 普通值
			if node.Type != model.FieldType_Struct {

				if node.IsRepeated {

					// repeated 值序列
					for arrIndex, valueNode := range node.Child {

						bf.Printf("%s", valueWrapperJson(node.Type, valueNode))

						// 多个值分割
						if arrIndex < len(node.Child)-1 {
							bf.Printf(", ")
						}

					}
				} else {
					// 单值
					valueNode := node.Child[0]

					bf.Printf("%s", valueWrapperJson(node.Type, valueNode))

				}

			} else {

				// 遍历repeated的结构体
				for structIndex, structNode := range node.Child {

					// 结构体开始
					bf.Printf("{ ")

					// 遍历一个结构体的字段
					for structFieldIndex, fieldNode := range structNode.Child {

						// 值节点总是在第一个
						valueNode := fieldNode.Child[0]

						bf.Printf("\"%s\": %s", fieldNode.Name, valueWrapperJson(fieldNode.Type, valueNode))

						// 结构体字段分割
						if structFieldIndex < len(structNode.Child)-1 {
							bf.Printf(", ")
						}

					}

					// 结构体结束
					bf.Printf(" }")

					// 多个结构体分割
					if structIndex < len(node.Child)-1 {
						bf.Printf(", ")
					}

				}

			}

			if node.IsRepeated {
				bf.Printf(" ]")
			}

			// 根字段分割
			if rootFieldIndex < len(r.Nodes)-1 {
				bf.Printf(", ")
			}

		}

		bf.Printf(" }")

		if rIndex < len(tab.Recs)-1 {
			bf.Printf(",")
		}

		bf.Printf("\n")

	}

	bf.Printf("	]")

	return true

}

func init() {

	RegisterPrinter("json", &jsonPrinter{})

}
<|endoftext|>


<commit_before>package product

import (
	"log"
	"net/rpc"

	"github.com/codegangsta/cli"
	"github.com/hashicorp/go-plugin"
)

type Meta struct {
	Name       string
	Properties map[string]interface{}
}

// ProductDeployer is the interface that we will expose for cloud config
// plugins
type ProductDeployer interface {
	GetMeta() Meta
	GetFlags() []cli.Flag
	GetProduct(args []string, cloudConfig []byte) []byte
}

// ProductRPC - Here is an implementation that talks over RPC
type ProductRPC struct{ client *rpc.Client }

func (s *ProductRPC) GetMeta() Meta {
	var resp Meta
	err := s.client.Call("Plugin.GetMeta", new(interface{}), &resp)

	if err != nil {
		panic(err)
	}
	return resp
}

type RPCArgs struct {
	Arg1 []string
	Arg2 []byte
}

func (s *ProductRPC) GetProduct(args []string, cloudConfig []byte) []byte {
	var resp []byte
	log.Println("calling rpc client getcloudconfig")
	err := s.client.Call("Plugin.GetProduct", RPCArgs{
		Arg1: args,
		Arg2: cloudConfig,
	}, &resp)
	log.Println("call:", err)
	if err != nil {
		panic(err)
	}
	return resp
}

func (s *ProductRPC) GetFlags() []cli.Flag {
	var resp []cli.Flag
	err := s.client.Call("Plugin.GetFlags", new(interface{}), &resp)
	log.Println("call: ", err)

	if err != nil {
		panic(err)
	}
	return resp
}

//ProductRPCServer - Here is the RPC server that ProductRPC talks to, conforming to
// the requirements of net/rpc
type ProductRPCServer struct {
	Impl ProductDeployer
}

func (s *ProductRPCServer) GetFlags(args interface{}, resp *[]cli.Flag) error {
	*resp = s.Impl.GetFlags()
	return nil
}

func (s *ProductRPCServer) GetMeta(args interface{}, resp *Meta) error {
	*resp = s.Impl.GetMeta()
	return nil
}

func (s *ProductRPCServer) GetProduct(args RPCArgs, resp *[]byte) error {
	*resp = s.Impl.GetProduct(args.Arg1, args.Arg2)
	return nil
}

func NewProductPlugin(plg ProductDeployer) ProductPlugin {
	return ProductPlugin{
		Plugin: plg,
	}
}

type ProductPlugin struct {
	Plugin ProductDeployer
}

func (s ProductPlugin) Server(*plugin.MuxBroker) (interface{}, error) {
	return &ProductRPCServer{Impl: s.Plugin}, nil
}

func (s ProductPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
	return &ProductRPC{client: c}, nil
}
<commit_msg>[#120196347] fixing incorrect godoc comment<commit_after>package product

import (
	"log"
	"net/rpc"

	"github.com/codegangsta/cli"
	"github.com/hashicorp/go-plugin"
)

type Meta struct {
	Name       string
	Properties map[string]interface{}
}

// ProductDeployer is the interface that we will expose for product
// plugins
type ProductDeployer interface {
	GetMeta() Meta
	GetFlags() []cli.Flag
	GetProduct(args []string, cloudConfig []byte) []byte
}

// ProductRPC - Here is an implementation that talks over RPC
type ProductRPC struct{ client *rpc.Client }

func (s *ProductRPC) GetMeta() Meta {
	var resp Meta
	err := s.client.Call("Plugin.GetMeta", new(interface{}), &resp)

	if err != nil {
		panic(err)
	}
	return resp
}

type RPCArgs struct {
	Arg1 []string
	Arg2 []byte
}

func (s *ProductRPC) GetProduct(args []string, cloudConfig []byte) []byte {
	var resp []byte
	log.Println("calling rpc client getcloudconfig")
	err := s.client.Call("Plugin.GetProduct", RPCArgs{
		Arg1: args,
		Arg2: cloudConfig,
	}, &resp)
	log.Println("call:", err)
	if err != nil {
		panic(err)
	}
	return resp
}

func (s *ProductRPC) GetFlags() []cli.Flag {
	var resp []cli.Flag
	err := s.client.Call("Plugin.GetFlags", new(interface{}), &resp)
	log.Println("call: ", err)

	if err != nil {
		panic(err)
	}
	return resp
}

//ProductRPCServer - Here is the RPC server that ProductRPC talks to, conforming to
// the requirements of net/rpc
type ProductRPCServer struct {
	Impl ProductDeployer
}

func (s *ProductRPCServer) GetFlags(args interface{}, resp *[]cli.Flag) error {
	*resp = s.Impl.GetFlags()
	return nil
}

func (s *ProductRPCServer) GetMeta(args interface{}, resp *Meta) error {
	*resp = s.Impl.GetMeta()
	return nil
}

func (s *ProductRPCServer) GetProduct(args RPCArgs, resp *[]byte) error {
	*resp = s.Impl.GetProduct(args.Arg1, args.Arg2)
	return nil
}

func NewProductPlugin(plg ProductDeployer) ProductPlugin {
	return ProductPlugin{
		Plugin: plg,
	}
}

type ProductPlugin struct {
	Plugin ProductDeployer
}

func (s ProductPlugin) Server(*plugin.MuxBroker) (interface{}, error) {
	return &ProductRPCServer{Impl: s.Plugin}, nil
}

func (s ProductPlugin) Client(b *plugin.MuxBroker, c *rpc.Client) (interface{}, error) {
	return &ProductRPC{client: c}, nil
}
<|endoftext|>


<commit_before><commit_msg>Fix txfeed panic when wallet disabled (#151)<commit_after><|endoftext|>


<commit_before>package job

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
)

// A JobResponse is sent as a notification -- it includes the success
// status as well as a subset of the job fields.
type JobResponse struct {
	Success  bool    `json:"success"`
	Errors   []error `json:"errors"`
	Callback string  `json:"callback"`
}

// NewFromJSON constructs a Job from an io.Reader containing JSON
// conforming to the required portion of the Job schema.
func NewFromJSON(encoded io.Reader) (newJob *Job, err error) {
	newJob = &Job{}
	err = json.NewDecoder(encoded).Decode(newJob)
	if err != nil {
		return
	}
	if !newJob.IsValid() {
		err = errors.New("missing required fields")
		return
	}
	err = newJob.setup()
	return
}

// ToJSON serializes the Job into a JSON byte slice.
func (j *Job) ToJSON() (jsonResponse []byte) {
	response := JobResponse{
		Success:  j.IsSuccessful(),
		Errors:   j.Errors,
		Callback: j.Callback,
	}
	jsonResponse, _ = json.Marshal(response)
	return
}

// Recipient returns the notification URL to send status updates to.
func (j *Job) Recipient() string {
	return j.Callback
}

// Content returns a Reader object that yields the job as JSON.
func (j *Job) Content() io.Reader {
	return bytes.NewReader(j.ToJSON())
}
<commit_msg>Stringify errors before sending them out<commit_after>package job

import (
	"bytes"
	"encoding/json"
	"errors"
	"io"
)

// A JobResponse is sent as a notification -- it includes the success
// status as well as a subset of the job fields.
type JobResponse struct {
	Success  bool     `json:"success"`
	Errors   []string `json:"errors"`
	Callback string   `json:"callback"`
}

// NewFromJSON constructs a Job from an io.Reader containing JSON
// conforming to the required portion of the Job schema.
func NewFromJSON(encoded io.Reader) (newJob *Job, err error) {
	newJob = &Job{}
	err = json.NewDecoder(encoded).Decode(newJob)
	if err != nil {
		return
	}
	if !newJob.IsValid() {
		err = errors.New("missing required fields")
		return
	}
	err = newJob.setup()
	return
}

// ToJSON serializes the Job into a JSON byte slice.
func (j *Job) ToJSON() (jsonResponse []byte) {
	response := JobResponse{
		Success:  j.IsSuccessful(),
		Errors:   errStrs(j.Errors),
		Callback: j.Callback,
	}
	jsonResponse, _ = json.Marshal(response)
	return
}

func errStrs(errors []error) (strings []string) {
	strings = make([]string, len(errors))
	for i, err := range errors {
		strings[i] = err.Error()
	}
	return
}

// Recipient returns the notification URL to send status updates to.
func (j *Job) Recipient() string {
	return j.Callback
}

// Content returns a Reader object that yields the job as JSON.
func (j *Job) Content() io.Reader {
	return bytes.NewReader(j.ToJSON())
}
<|endoftext|>


<commit_before>package binding

import (
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"
)

// Bind takes data out of the request and deserializes into a struct according
// to the Content-Type of the request. If no Content-Type is specified, there
// better be data in the query string, otherwise an error will be produced.
func Bind(req *http.Request, userStruct FieldMapper) Errors {
	var errs Errors

	contentType := req.Header.Get("Content-Type")

	if strings.Contains(contentType, "form-urlencoded") {
		return Form(req, userStruct)
	}

	if strings.Contains(contentType, "multipart/form-data") {
		return MultipartForm(req, userStruct)
	}

	if strings.Contains(contentType, "json") {
		return Json(req, userStruct)
	}

	if contentType == "" {
		if len(req.URL.Query()) > 0 {
			return Form(req, userStruct)
		} else {
			errs.Add([]string{}, ContentTypeError, "Empty Content-Type")
		}
	} else {
		errs.Add([]string{}, ContentTypeError, "Unsupported Content-Type")
	}

	return errs
}

// Form deserializes form data out of the request into a struct you provide.
// This function invokes data validation after deserialization.
func Form(req *http.Request, userStruct FieldMapper) Errors {
	var errs Errors

	parseErr := req.ParseForm()
	if parseErr != nil {
		errs.Add([]string{}, DeserializationError, parseErr.Error())
		return errs
	}

	fm := userStruct.FieldMap()
	for fieldName, fieldPointer := range fm {
		str := req.Form.Get(fieldName)

		if str == "" {
			continue
		}

		fieldSpec, fieldHasSpec := fieldPointer.(Field)
		if fieldHasSpec {
			fieldPointer = fieldSpec.Target
		}

		errorHandler := func(err error) {
			if err != nil {
				errs.Add([]string{fieldName}, TypeError, err.Error())
			}
		}

		if fieldSpec.Binder != nil {
			fieldSpec.Binder(str, &errs)
		}

		switch t := fieldPointer.(type) {
		case *uint8:
			val, err := strconv.ParseUint(str, 10, 8)
			errorHandler(err)
			*t = uint8(val)
		case *uint16:
			val, err := strconv.ParseUint(str, 10, 16)
			errorHandler(err)
			*t = uint16(val)
		case *uint32:
			val, err := strconv.ParseUint(str, 10, 32)
			errorHandler(err)
			*t = uint32(val)
		case *uint64:
			val, err := strconv.ParseUint(str, 10, 64)
			errorHandler(err)
			*t = val
		case *int8:
			val, err := strconv.ParseInt(str, 10, 8)
			errorHandler(err)
			*t = int8(val)
		case *int16:
			val, err := strconv.ParseInt(str, 10, 16)
			errorHandler(err)
			*t = int16(val)
		case *int32:
			val, err := strconv.ParseInt(str, 10, 32)
			errorHandler(err)
			*t = int32(val)
		case *int64:
			val, err := strconv.ParseInt(str, 10, 64)
			errorHandler(err)
			*t = val
		case *float32:
			val, err := strconv.ParseFloat(str, 32)
			errorHandler(err)
			*t = float32(val)
		case *float64:
			val, err := strconv.ParseFloat(str, 64)
			errorHandler(err)
			*t = val
		case *uint:
			val, err := strconv.ParseUint(str, 10, 0)
			errorHandler(err)
			*t = uint(val)
		case *int:
			val, err := strconv.ParseInt(str, 10, 0)
			errorHandler(err)
			*t = int(val)
		case *bool:
			val, err := strconv.ParseBool(str)
			errorHandler(err)
			*t = val
		case *string:
			*t = str
		case *time.Time:
			timeFormat := TimeFormat
			if fieldSpec.TimeFormat != "" {
				timeFormat = fieldSpec.TimeFormat
			}
			val, err := time.Parse(timeFormat, str)
			errorHandler(err)
			*t = val
		default:
			errorHandler(errors.New("Field type is unsupported by the application"))
		}
	}

	errs = append(errs, Validate(req, userStruct)...)

	return errs
}

// MultipartForm reads a multipart form request and deserializes its data into
// a struct you provide. It then calls Form to get the rest of the form data
// out of the request.
func MultipartForm(req *http.Request, userStruct FieldMapper) (errs Errors) {
	multipartReader, err := req.MultipartReader()
	if err != nil {
		errs.Add([]string{}, DeserializationError, err.Error())
		return
	} else {
		form, parseErr := multipartReader.ReadForm(MaxMemory)
		if parseErr != nil {
			errs.Add([]string{}, DeserializationError, parseErr.Error())
			return
		}
		req.MultipartForm = form
	}
	return Form(req, userStruct)
}

// Json deserializes a JSON request body into a struct you specify
// using the standard encoding/json package (which uses reflection).
// This function invokes data validation after deserialization.
func Json(req *http.Request, userStruct FieldMapper) (errs Errors) {
	if req.Body != nil {
		defer req.Body.Close()
		err := json.NewDecoder(req.Body).Decode(userStruct)
		if err != nil && err != io.EOF {
			errs.Add([]string{}, DeserializationError, err.Error())
			return
		}
	} else {
		errs.Add([]string{}, DeserializationError, "Empty request body")
		return
	}

	errs = append(errs, Validate(req, userStruct)...)

	return
}

// Validate ensures that all conditions have been met on every field in the
// populated struct. Validation should occur after the request has been
// deserialized into the struct.
func Validate(req *http.Request, userStruct FieldMapper) (errs Errors) {
	fm := userStruct.FieldMap()

	for fieldName, fieldSpec := range fm {
		addRequiredError := func() {
			errs.Add([]string{fieldName}, RequiredError, "Required")
		}

		if field, ok := fieldSpec.(Field); ok {
			if field.Required {
				switch t := field.Target.(type) {
				case *uint8:
					if *t == 0 {
						addRequiredError()
					}
				case *uint16:
					if *t == 0 {
						addRequiredError()
					}
				case *uint32:
					if *t == 0 {
						addRequiredError()
					}
				case *uint64:
					if *t == 0 {
						addRequiredError()
					}
				case *int8:
					if *t == 0 {
						addRequiredError()
					}
				case *int16:
					if *t == 0 {
						addRequiredError()
					}
				case *int32:
					if *t == 0 {
						addRequiredError()
					}
				case *int64:
					if *t == 0 {
						addRequiredError()
					}
				case *float32:
					if *t == 0 {
						addRequiredError()
					}
				case *float64:
					if *t == 0 {
						addRequiredError()
					}
				case *uint:
					if *t == 0 {
						addRequiredError()
					}
				case *int:
					if *t == 0 {
						addRequiredError()
					}
				case *bool:
					if !*t == false {
						addRequiredError()
					}
				case *string:
					if *t == "" {
						addRequiredError()
					}
				case *time.Time:
					if t.IsZero() {
						addRequiredError()
					}
				}
			}
		}
	}

	if validator, ok := userStruct.(Validator); ok {
		errs = validator.Validate(errs, req)
	}

	return
}

type (
	// Only types that are FieldMappers can be used to bind requests.
	FieldMapper interface {

		// FieldMap returns a map that keys field names from the request
		// to pointers into which the values will be deserialized.
		FieldMap() FieldMap
	}

	// FieldMap is a map of field names in the request to pointers into
	// which the values will be deserialized.
	FieldMap map[string]interface{}

	// Field describes the properties of a field.
	Field struct {
		Target     interface{}
		Required   bool
		TimeFormat string
		Binder     func(string, *Errors)
	}

	// Validator can be implemented by your type to handle some
	// rudimentary request validation separately from your
	// application logic.
	Validator interface {
		// Validate validates that the request is OK. It is recommended
		// that validation be limited to checking values for syntax and
		// semantics, enough to know that you can make sense of the request
		// in your application. For example, you might verify that a credit
		// card number matches a valid pattern, but you probably wouldn't
		// perform an actual credit card authorization here.
		Validate(Errors, *http.Request) Errors
	}
)

var (
	// Maximum amount of memory to use when parsing a multipart form.
	// Set this to whatever value you prefer; default is 10 MB.
	MaxMemory = int64(1024 * 1024 * 10)

	// If no TimeFormat is specified for a time.Time field, this
	// format will be used by default when parsing.
	TimeFormat = time.RFC3339
)

const (
	jsonContentType           = "application/json; charset=utf-8"
	StatusUnprocessableEntity = 422
)
<commit_msg>Removed named returns; also a bug fix for using a Binder function<commit_after>package binding

import (
	"encoding/json"
	"errors"
	"io"
	"net/http"
	"strconv"
	"strings"
	"time"
)

// Bind takes data out of the request and deserializes into a struct according
// to the Content-Type of the request. If no Content-Type is specified, there
// better be data in the query string, otherwise an error will be produced.
func Bind(req *http.Request, userStruct FieldMapper) Errors {
	var errs Errors

	contentType := req.Header.Get("Content-Type")

	if strings.Contains(contentType, "form-urlencoded") {
		return Form(req, userStruct)
	}

	if strings.Contains(contentType, "multipart/form-data") {
		return MultipartForm(req, userStruct)
	}

	if strings.Contains(contentType, "json") {
		return Json(req, userStruct)
	}

	if contentType == "" {
		if len(req.URL.Query()) > 0 {
			return Form(req, userStruct)
		} else {
			errs.Add([]string{}, ContentTypeError, "Empty Content-Type")
		}
	} else {
		errs.Add([]string{}, ContentTypeError, "Unsupported Content-Type")
	}

	return errs
}

// Form deserializes form data out of the request into a struct you provide.
// This function invokes data validation after deserialization.
func Form(req *http.Request, userStruct FieldMapper) Errors {
	var errs Errors

	parseErr := req.ParseForm()
	if parseErr != nil {
		errs.Add([]string{}, DeserializationError, parseErr.Error())
		return errs
	}

	fm := userStruct.FieldMap()
	for fieldName, fieldPointer := range fm {
		str := req.Form.Get(fieldName)

		if str == "" {
			continue
		}

		fieldSpec, fieldHasSpec := fieldPointer.(Field)
		if fieldHasSpec {
			fieldPointer = fieldSpec.Target
		}

		errorHandler := func(err error) {
			if err != nil {
				errs.Add([]string{fieldName}, TypeError, err.Error())
			}
		}

		if fieldSpec.Binder != nil {
			fieldSpec.Binder(str, &errs)
			continue
		}

		switch t := fieldPointer.(type) {
		case *uint8:
			val, err := strconv.ParseUint(str, 10, 8)
			errorHandler(err)
			*t = uint8(val)
		case *uint16:
			val, err := strconv.ParseUint(str, 10, 16)
			errorHandler(err)
			*t = uint16(val)
		case *uint32:
			val, err := strconv.ParseUint(str, 10, 32)
			errorHandler(err)
			*t = uint32(val)
		case *uint64:
			val, err := strconv.ParseUint(str, 10, 64)
			errorHandler(err)
			*t = val
		case *int8:
			val, err := strconv.ParseInt(str, 10, 8)
			errorHandler(err)
			*t = int8(val)
		case *int16:
			val, err := strconv.ParseInt(str, 10, 16)
			errorHandler(err)
			*t = int16(val)
		case *int32:
			val, err := strconv.ParseInt(str, 10, 32)
			errorHandler(err)
			*t = int32(val)
		case *int64:
			val, err := strconv.ParseInt(str, 10, 64)
			errorHandler(err)
			*t = val
		case *float32:
			val, err := strconv.ParseFloat(str, 32)
			errorHandler(err)
			*t = float32(val)
		case *float64:
			val, err := strconv.ParseFloat(str, 64)
			errorHandler(err)
			*t = val
		case *uint:
			val, err := strconv.ParseUint(str, 10, 0)
			errorHandler(err)
			*t = uint(val)
		case *int:
			val, err := strconv.ParseInt(str, 10, 0)
			errorHandler(err)
			*t = int(val)
		case *bool:
			val, err := strconv.ParseBool(str)
			errorHandler(err)
			*t = val
		case *string:
			*t = str
		case *time.Time:
			timeFormat := TimeFormat
			if fieldSpec.TimeFormat != "" {
				timeFormat = fieldSpec.TimeFormat
			}
			val, err := time.Parse(timeFormat, str)
			errorHandler(err)
			*t = val
		default:
			errorHandler(errors.New("Field type is unsupported by the application"))
		}
	}

	errs = append(errs, Validate(req, userStruct)...)

	return errs
}

// MultipartForm reads a multipart form request and deserializes its data into
// a struct you provide. It then calls Form to get the rest of the form data
// out of the request.
// TODO: This implementation is not complete yet
func MultipartForm(req *http.Request, userStruct FieldMapper) Errors {
	var errs Errors

	multipartReader, err := req.MultipartReader()
	if err != nil {
		errs.Add([]string{}, DeserializationError, err.Error())
		return errs
	} else {
		form, parseErr := multipartReader.ReadForm(MaxMemory)
		if parseErr != nil {
			errs.Add([]string{}, DeserializationError, parseErr.Error())
			return errs
		}
		req.MultipartForm = form
	}
	return Form(req, userStruct)
}

// Json deserializes a JSON request body into a struct you specify
// using the standard encoding/json package (which uses reflection).
// This function invokes data validation after deserialization.
func Json(req *http.Request, userStruct FieldMapper) Errors {
	var errs Errors

	if req.Body != nil {
		defer req.Body.Close()
		err := json.NewDecoder(req.Body).Decode(userStruct)
		if err != nil && err != io.EOF {
			errs.Add([]string{}, DeserializationError, err.Error())
			return errs
		}
	} else {
		errs.Add([]string{}, DeserializationError, "Empty request body")
		return errs
	}

	errs = append(errs, Validate(req, userStruct)...)

	return errs
}

// Validate ensures that all conditions have been met on every field in the
// populated struct. Validation should occur after the request has been
// deserialized into the struct.
func Validate(req *http.Request, userStruct FieldMapper) Errors {
	var errs Errors

	fm := userStruct.FieldMap()

	for fieldName, fieldSpec := range fm {
		addRequiredError := func() {
			errs.Add([]string{fieldName}, RequiredError, "Required")
		}

		if field, ok := fieldSpec.(Field); ok {
			if field.Required {
				switch t := field.Target.(type) {
				case *uint8:
					if *t == 0 {
						addRequiredError()
					}
				case *uint16:
					if *t == 0 {
						addRequiredError()
					}
				case *uint32:
					if *t == 0 {
						addRequiredError()
					}
				case *uint64:
					if *t == 0 {
						addRequiredError()
					}
				case *int8:
					if *t == 0 {
						addRequiredError()
					}
				case *int16:
					if *t == 0 {
						addRequiredError()
					}
				case *int32:
					if *t == 0 {
						addRequiredError()
					}
				case *int64:
					if *t == 0 {
						addRequiredError()
					}
				case *float32:
					if *t == 0 {
						addRequiredError()
					}
				case *float64:
					if *t == 0 {
						addRequiredError()
					}
				case *uint:
					if *t == 0 {
						addRequiredError()
					}
				case *int:
					if *t == 0 {
						addRequiredError()
					}
				case *bool:
					if !*t == false {
						addRequiredError()
					}
				case *string:
					if *t == "" {
						addRequiredError()
					}
				case *time.Time:
					if t.IsZero() {
						addRequiredError()
					}
				}
			}
		}
	}

	if validator, ok := userStruct.(Validator); ok {
		errs = validator.Validate(errs, req)
	}

	return errs
}

type (
	// Only types that are FieldMappers can be used to bind requests.
	FieldMapper interface {

		// FieldMap returns a map that keys field names from the request
		// to pointers into which the values will be deserialized.
		FieldMap() FieldMap
	}

	// FieldMap is a map of field names in the request to pointers into
	// which the values will be deserialized.
	FieldMap map[string]interface{}

	// Field describes the properties of a field.
	Field struct {
		Target     interface{}
		Required   bool
		TimeFormat string
		Binder     func(string, *Errors)
	}

	// Validator can be implemented by your type to handle some
	// rudimentary request validation separately from your
	// application logic.
	Validator interface {
		// Validate validates that the request is OK. It is recommended
		// that validation be limited to checking values for syntax and
		// semantics, enough to know that you can make sense of the request
		// in your application. For example, you might verify that a credit
		// card number matches a valid pattern, but you probably wouldn't
		// perform an actual credit card authorization here.
		Validate(Errors, *http.Request) Errors
	}
)

var (
	// Maximum amount of memory to use when parsing a multipart form.
	// Set this to whatever value you prefer; default is 10 MB.
	MaxMemory = int64(1024 * 1024 * 10)

	// If no TimeFormat is specified for a time.Time field, this
	// format will be used by default when parsing.
	TimeFormat = time.RFC3339
)

const (
	jsonContentType           = "application/json; charset=utf-8"
	StatusUnprocessableEntity = 422
)
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"regexp"
	"strconv"

	logrus "github.com/Sirupsen/logrus"
	docopt "github.com/docopt/docopt-go"

	"./app/commands"
	"./app/environments"
	"./app/slices"
)

const OPTIONS = `ah - A better history.

Ah is a better way to traverse the history of your shell prompts. Right now it supports only 3 additional possibilities you are probably have dreamt about:
    1. Good searching;
    2. Better memoizing of entries;
    3. Storing an output of the commands.

Searching is done using 's' command. You may filter output or fetch a history slice you are wondering about. Filtering uses regular expressions or fuzzy matching out of box.

Memoizing means that you have an ability to bookmark some favourite commands and use ah to store some sort of short snippets or ad-hoc shell scripts.

And ah gives you a possibility to have a persistent storage of an output of any command you are executing. And you can return back to it any time you want.

Usage:
    ah [options] s [-z] [-g PATTERN] [<lastNcommands> | <startFromNCommand> <finishByMCommand>]
    ah [options] b <commandNumber> <bookmarkAs>
    ah [options] e <commandNumberOrBookMarkName>
    ah [options] t [-y] [--] <command>...
    ah [options] l <numberOfCommandYouWantToCheck>
	ah [options] g [--keepLatest <keepLatest> | --olderThan <olderThan>]
    ah (-h | --help)
    ah --version

Options:
    -s SHELL, --shell=SHELL                               Shell flavour you are using. By default, ah will do some shallow investigations.
    -f HISTFILE, --histfile=HISTFILE                      The path to a history file. By default ah will try to use default history file of your shell
    -t HISTTIMEFORMAT, --histtimeformat=HISTTIMEFORMAT    A time format for history output. Will use $HISTTIMEFORMAT by default.
    -d APPDIR, --appdir=APPDIR                            A place where ah has to store its data.
    -g PATTERN, --grep PATTERN                            A pattern to filter command lines. It is regular expression if no -f option is set.
    -y, --tty                                             Allocates pseudo-tty is necessary
	-z, --fuzzy                                           Interpret -g pattern as fuzzy match string.
    -v, --debug                                           Shows a debug log of command execution.`

const (
	VERSION = "ah 0.4"

	DEFAULT_APP_DIR = ".ah"
)

var (
	VALIDATE_BOOKMARK_NAME = regexp.MustCompile(`^\w(\w|\d)*$`)
)

type executor func(arguments map[string]interface{}, env *environments.Environment)

func main() {
	defer func() {
		if exc := recover(); exc != nil {
			os.Stderr.WriteString(fmt.Sprintf("%v\n", exc))
			os.Exit(1)
		}
	}()

	arguments, err := docopt.Parse(OPTIONS, nil, true, VERSION, false)
	if err != nil {
		panic(err)
	}

	env := new(environments.Environment)

	argShell := arguments["--shell"]
	if argShell == nil {
		env.DiscoverShell()
	} else {
		env.SetShell(argShell.(string))
	}

	argHistFile := arguments["--histfile"]
	if argHistFile == nil {
		env.DiscoverHistFile()
	} else {
		env.SetHistFile(argHistFile.(string))
	}

	argHistTimeFormat := arguments["--histtimeformat"]
	if argHistTimeFormat != nil {
		env.SetHistTimeFormat(argHistTimeFormat.(string))
	}

	argAppDir := arguments["--appdir"]
	if argAppDir == nil {
		env.DiscoverAppDir()
	} else {
		env.SetAppDir(argAppDir.(string))
	}

	if arguments["--debug"].(bool) {
		env.EnableDebugLog()
	} else {
		env.DisableDebugLog()
	}

	logger, _ := env.GetLogger()
	logger.WithFields(arguments).Debug("Arguments")
	logger.Debug("Environment ", env)

	logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetTracesDir(), 0777),
	}).Info("Create traces dir")
	logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetBookmarksDir(), 0777),
	}).Info("Create bookmarks dir")

	var exec executor
	if arguments["t"].(bool) {
		logger.Info("Execute command 'tee'")
		exec = executeTee
	} else if arguments["s"].(bool) {
		logger.Info("Execute command 'show'")
		exec = executeShow
	} else if arguments["l"].(bool) {
		logger.Info("Execute command 'listTrace'")
		exec = executeListTrace
	} else if arguments["b"].(bool) {
		logger.Info("Execute command 'bookmark'")
		exec = executeBookmark
	} else if arguments["e"].(bool) {
		logger.Info("Execute command 'execute'")
		exec = executeExec
	} else if arguments["g"].(bool) {
		logger.Info("Execute command 'gc'")
		exec = executeGC
	} else {
		logger.Info("No valid choices", arguments)
		panic("Unknown command. Please be more precise")
	}
	exec(arguments, env)
}

func executeTee(arguments map[string]interface{}, env *environments.Environment) {
	cmds := arguments["<command>"].([]string)
	tty := arguments["--tty"].(bool)

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"command arguments": cmds,
		"pseudo-tty":        tty,
	}).Info("Arguments of 'tee'")

	commands.Tee(cmds, tty, env)
}

func executeShow(arguments map[string]interface{}, env *environments.Environment) {
	logger, _ := env.GetLogger()

	slice, err := slices.ExtractSlice(
		arguments["<lastNcommands>"],
		arguments["<startFromNCommand>"],
		arguments["<finishByMCommand>"])
	if err != nil {
		panic(err)
	}

	var filter *regexp.Regexp
	if arguments["--grep"] != nil {
		query := arguments["--grep"].(string)
		if arguments["--fuzzy"].(bool) {
			regex := ""
			for _, character := range query {
				regex += ".*?" + regexp.QuoteMeta(string(character))
			}
			query = regex + ".*?"
		}
		filter = regexp.MustCompile(query)
	}

	logger.WithFields(logrus.Fields{
		"slice":  slice,
		"filter": filter,
	}).Info("Arguments of 'show'")

	commands.Show(slice, filter, env)
}

func executeListTrace(arguments map[string]interface{}, env *environments.Environment) {
	cmd := arguments["<numberOfCommandYouWantToCheck>"].(string)

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"cmd": cmd,
	}).Info("Arguments of 'listTrace'")

	commands.ListTrace(cmd, env)
}

func executeBookmark(arguments map[string]interface{}, env *environments.Environment) {
	var commandNumber int
	if number, err := strconv.Atoi(arguments["<commandNumber>"].(string)); err != nil {
		panic(fmt.Sprintf("Cannot understand command number: %s", commandNumber))
	} else {
		commandNumber = number
	}

	bookmarkAs := arguments["<bookmarkAs>"].(string)
	if !VALIDATE_BOOKMARK_NAME.MatchString(bookmarkAs) {
		panic("Incorrect bookmark name!")
	}

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"commandNumber": commandNumber,
		"bookmarkAs":    bookmarkAs,
	}).Info("Arguments of 'bookmark'")

	commands.Bookmark(commandNumber, bookmarkAs, env)
}

func executeExec(arguments map[string]interface{}, env *environments.Environment) {
	commandNumberOrBookMarkName := arguments["<commandNumberOrBookMarkName>"].(string)

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"commandNumberOrBookMarkName": commandNumberOrBookMarkName,
	}).Info("Arguments of 'bookmark'")

	if commandNumber, err := strconv.Atoi(commandNumberOrBookMarkName); err == nil {
		logger.Info("Execute command number ", commandNumber)
		commands.ExecuteCommandNumber(commandNumber, env)
	} else if VALIDATE_BOOKMARK_NAME.MatchString(commandNumberOrBookMarkName) {
		logger.Info("Execute bookmark ", commandNumberOrBookMarkName)
		commands.ExecuteBookmark(commandNumberOrBookMarkName, env)
	} else {
		panic("Incorrect bookmark name! It should be started with alphabet letter, and alphabet or digits after!")
	}
}

func executeGC(arguments map[string]interface{}, env *environments.Environment) {
	var param int
	var gcType commands.GcType

	if arguments["--keepLatest"].(bool) {
		gcType = commands.GC_KEEP_LATEST
		paramString := arguments["<keepLatest>"].(string)
		paramConverted, err := strconv.Atoi(paramString)
		if err != nil {
			panic(err)
		}
		param = paramConverted
	} else if arguments["--olderThan"].(bool) {
		gcType = commands.GC_OLDER_THAN
		paramString := arguments["<olderThan>"].(string)
		paramConverted, err := strconv.Atoi(paramString)
		if err != nil {
			panic(err)
		}
		param = paramConverted
	} else {
		panic("Unknown command")
	}

	if param <= 0 {
		panic("Parameter of garbage collection has to be > 0")
	}

	commands.GC(gcType, param, env)
}
<commit_msg>Format fixes<commit_after>package main

import (
	"fmt"
	"os"
	"regexp"
	"strconv"

	logrus "github.com/Sirupsen/logrus"
	docopt "github.com/docopt/docopt-go"

	"./app/commands"
	"./app/environments"
	"./app/slices"
)

const OPTIONS = `ah - A better history.

Ah is a better way to traverse the history of your shell prompts. Right now it
supports only 3 additional possibilities you are probably have dreamt about:
    1. Good searching;
    2. Better memoizing of entries;
    3. Storing an output of the commands.

Searching is done using 's' command. You may filter output or fetch a history
slice you are wondering about. Filtering uses regular expressions or fuzzy
matching out of box.

Memoizing means that you have an ability to bookmark some favourite commands
and use ah to store some sort of short snippets or ad-hoc shell scripts.

And ah gives you a possibility to have a persistent storage of an output
of any command you are executing. And you can return back to it any time
you want.

Usage:
    ah [options] s [-z] [-g PATTERN] [<lastNcommands> | <startFromNCommand> <finishByMCommand>]
    ah [options] b <commandNumber> <bookmarkAs>
    ah [options] e <commandNumberOrBookMarkName>
    ah [options] t [-y] [--] <command>...
    ah [options] l <numberOfCommandYouWantToCheck>
    ah [options] g [--keepLatest <keepLatest> | --olderThan <olderThan>]
    ah (-h | --help)
    ah --version

Options:
    -s SHELL, --shell=SHELL                               Shell flavour you are using. By default, ah will do some shallow investigations.
    -f HISTFILE, --histfile=HISTFILE                      The path to a history file. By default ah will try to use default history file of your shell
    -t HISTTIMEFORMAT, --histtimeformat=HISTTIMEFORMAT    A time format for history output. Will use $HISTTIMEFORMAT by default.
    -d APPDIR, --appdir=APPDIR                            A place where ah has to store its data.
    -g PATTERN, --grep PATTERN                            A pattern to filter command lines. It is regular expression if no -f option is set.
    -y, --tty                                             Allocates pseudo-tty is necessary
    -z, --fuzzy                                           Interpret -g pattern as fuzzy match string.
    -v, --debug                                           Shows a debug log of command execution.`

const (
	VERSION = "ah 0.4"

	DEFAULT_APP_DIR = ".ah"
)

var (
	VALIDATE_BOOKMARK_NAME = regexp.MustCompile(`^\w(\w|\d)*$`)
)

type executor func(arguments map[string]interface{}, env *environments.Environment)

func main() {
	defer func() {
		if exc := recover(); exc != nil {
			os.Stderr.WriteString(fmt.Sprintf("%v\n", exc))
			os.Exit(1)
		}
	}()

	arguments, err := docopt.Parse(OPTIONS, nil, true, VERSION, false)
	if err != nil {
		panic(err)
	}

	env := new(environments.Environment)

	argShell := arguments["--shell"]
	if argShell == nil {
		env.DiscoverShell()
	} else {
		env.SetShell(argShell.(string))
	}

	argHistFile := arguments["--histfile"]
	if argHistFile == nil {
		env.DiscoverHistFile()
	} else {
		env.SetHistFile(argHistFile.(string))
	}

	argHistTimeFormat := arguments["--histtimeformat"]
	if argHistTimeFormat != nil {
		env.SetHistTimeFormat(argHistTimeFormat.(string))
	}

	argAppDir := arguments["--appdir"]
	if argAppDir == nil {
		env.DiscoverAppDir()
	} else {
		env.SetAppDir(argAppDir.(string))
	}

	if arguments["--debug"].(bool) {
		env.EnableDebugLog()
	} else {
		env.DisableDebugLog()
	}

	logger, _ := env.GetLogger()
	logger.WithFields(arguments).Debug("Arguments")
	logger.Debug("Environment ", env)

	logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetTracesDir(), 0777),
	}).Info("Create traces dir")
	logger.WithFields(logrus.Fields{
		"error": os.MkdirAll(env.GetBookmarksDir(), 0777),
	}).Info("Create bookmarks dir")

	var exec executor
	if arguments["t"].(bool) {
		logger.Info("Execute command 'tee'")
		exec = executeTee
	} else if arguments["s"].(bool) {
		logger.Info("Execute command 'show'")
		exec = executeShow
	} else if arguments["l"].(bool) {
		logger.Info("Execute command 'listTrace'")
		exec = executeListTrace
	} else if arguments["b"].(bool) {
		logger.Info("Execute command 'bookmark'")
		exec = executeBookmark
	} else if arguments["e"].(bool) {
		logger.Info("Execute command 'execute'")
		exec = executeExec
	} else if arguments["g"].(bool) {
		logger.Info("Execute command 'gc'")
		exec = executeGC
	} else {
		logger.Info("No valid choices", arguments)
		panic("Unknown command. Please be more precise")
	}
	exec(arguments, env)
}

func executeTee(arguments map[string]interface{}, env *environments.Environment) {
	cmds := arguments["<command>"].([]string)
	tty := arguments["--tty"].(bool)

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"command arguments": cmds,
		"pseudo-tty":        tty,
	}).Info("Arguments of 'tee'")

	commands.Tee(cmds, tty, env)
}

func executeShow(arguments map[string]interface{}, env *environments.Environment) {
	logger, _ := env.GetLogger()

	slice, err := slices.ExtractSlice(
		arguments["<lastNcommands>"],
		arguments["<startFromNCommand>"],
		arguments["<finishByMCommand>"])
	if err != nil {
		panic(err)
	}

	var filter *regexp.Regexp
	if arguments["--grep"] != nil {
		query := arguments["--grep"].(string)
		if arguments["--fuzzy"].(bool) {
			regex := ""
			for _, character := range query {
				regex += ".*?" + regexp.QuoteMeta(string(character))
			}
			query = regex + ".*?"
		}
		filter = regexp.MustCompile(query)
	}

	logger.WithFields(logrus.Fields{
		"slice":  slice,
		"filter": filter,
	}).Info("Arguments of 'show'")

	commands.Show(slice, filter, env)
}

func executeListTrace(arguments map[string]interface{}, env *environments.Environment) {
	cmd := arguments["<numberOfCommandYouWantToCheck>"].(string)

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"cmd": cmd,
	}).Info("Arguments of 'listTrace'")

	commands.ListTrace(cmd, env)
}

func executeBookmark(arguments map[string]interface{}, env *environments.Environment) {
	var commandNumber int
	if number, err := strconv.Atoi(arguments["<commandNumber>"].(string)); err != nil {
		panic(fmt.Sprintf("Cannot understand command number: %s", commandNumber))
	} else {
		commandNumber = number
	}

	bookmarkAs := arguments["<bookmarkAs>"].(string)
	if !VALIDATE_BOOKMARK_NAME.MatchString(bookmarkAs) {
		panic("Incorrect bookmark name!")
	}

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"commandNumber": commandNumber,
		"bookmarkAs":    bookmarkAs,
	}).Info("Arguments of 'bookmark'")

	commands.Bookmark(commandNumber, bookmarkAs, env)
}

func executeExec(arguments map[string]interface{}, env *environments.Environment) {
	commandNumberOrBookMarkName := arguments["<commandNumberOrBookMarkName>"].(string)

	logger, _ := env.GetLogger()
	logger.WithFields(logrus.Fields{
		"commandNumberOrBookMarkName": commandNumberOrBookMarkName,
	}).Info("Arguments of 'bookmark'")

	if commandNumber, err := strconv.Atoi(commandNumberOrBookMarkName); err == nil {
		logger.Info("Execute command number ", commandNumber)
		commands.ExecuteCommandNumber(commandNumber, env)
	} else if VALIDATE_BOOKMARK_NAME.MatchString(commandNumberOrBookMarkName) {
		logger.Info("Execute bookmark ", commandNumberOrBookMarkName)
		commands.ExecuteBookmark(commandNumberOrBookMarkName, env)
	} else {
		panic("Incorrect bookmark name! It should be started with alphabet letter, and alphabet or digits after!")
	}
}

func executeGC(arguments map[string]interface{}, env *environments.Environment) {
	var param int
	var gcType commands.GcType

	if arguments["--keepLatest"].(bool) {
		gcType = commands.GC_KEEP_LATEST
		paramString := arguments["<keepLatest>"].(string)
		paramConverted, err := strconv.Atoi(paramString)
		if err != nil {
			panic(err)
		}
		param = paramConverted
	} else if arguments["--olderThan"].(bool) {
		gcType = commands.GC_OLDER_THAN
		paramString := arguments["<olderThan>"].(string)
		paramConverted, err := strconv.Atoi(paramString)
		if err != nil {
			panic(err)
		}
		param = paramConverted
	} else {
		panic("Unknown command")
	}

	if param <= 0 {
		panic("Parameter of garbage collection has to be > 0")
	}

	commands.GC(gcType, param, env)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/the42/ogdat"
	htmltpl "html/template"
	"io"
	"log"
	"os"
	texttpl "text/template"
)

var inputfile = flag.String("if", "", "Eingabe mit OGD-Spezifikation (Standard: stdin)")
var outputfile = flag.String("of", "", "Ausgabe der Spezifikation nach (Standard: stdout)")
var templateset = flag.String("ts", "", "(Satz von) Template-Dateien, die die Transformation der Spezifikation ins Ausgabeformat beschreibt")
var html = flag.Bool("html", true, "Anwendung von HTML-Escaping in der Ausgabe")
var printbuiltin = flag.Bool("printbuiltin", false, "Ausgabe von eingebautem Template (stdout)")
var help = flag.Bool("help", false, "Hilfe zur Verwendung")

type Templater interface {
	Execute(io.Writer, interface{}) error
}

func main() {
	flag.Parse()

	// Display help and exit
	if *help {
		flag.PrintDefaults()
		return
	}

	// Display default template and exit
	if *printbuiltin {
		fmt.Print(builtintpl)
		return
	}

	// If no input spec file is given, read from stdin
	if *inputfile == "" {
		*inputfile = os.Stdin.Name()
	}
	spec, err := ogdat.Loadogdatspec("unknown", *inputfile)
	if err != nil {
		log.Panicf("Could not load specification file %s, the error was %s\n", *inputfile, err)
	}

	var tpl Templater
	if *templateset != "" { // If a template set was given, try to read it
		if *html {
			tpl = htmltpl.Must(htmltpl.ParseFiles(*templateset))
		} else {
			tpl = texttpl.Must(texttpl.ParseFiles(*templateset))
		}
	} else { // otherwise use the built-in
		tpl = htmltpl.Must(htmltpl.New("").Parse(builtintpl))
	}

	// Open the output file
	var ofile *os.File
	if *outputfile == "" {
		ofile = os.Stdout
	} else {
		var err error
		// Do not overwrite an exisiting file but fail
		ofile, err = os.OpenFile(*outputfile, os.O_RDWR|os.O_CREATE|os.O_EXCL, os.FileMode(0666))
		if err != nil {
			log.Panicf("Can't open file %s for writing, the error was: %s\n", inputfile, err)
		}
		defer ofile.Close()
	}
	if err := tpl.Execute(ofile, spec); err != nil {
		log.Panicf("Template execution failed: %s\n", err)
	}
	log.Printf("Sepcification successfully transformed\n")
}

const builtintpl = `
<!DOCTYPE html>

  <title></title>
  <meta charset="UTF-8">

{{range .Beschreibung}}

      {{index $.Label 0}}
      {{index $.Label 1}}
      {{index $.Label 2}}
      {{index $.Label 3}}
      {{index $.Label 4}}

      {{.ID}}
      {{.Bezeichner}}
      {{.OGD_Kurzname}}
      {{.CKAN_Feld}}
      {{.Anzahl}}

      {{index $.Label 5}}
      {{.Definition_DE}}

      {{index $.Label 6}}
      {{.Erlauterung}}

      {{index $.Label 7}}
      {{.Beispiel}}

      {{index $.Label 8}}
      {{.ONA2270}}

      {{index $.Label 9}}
      {{.ISO19115}}

      {{index $.Label 10}}
      {{.RDFProperty}}

      {{index $.Label 11}}
      {{.Definition_EN}}

{{end}}

`
<commit_msg>much simplify the builtin template<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/the42/ogdat"
	htmltpl "html/template"
	"io"
	"log"
	"os"
	texttpl "text/template"
)

var inputfile = flag.String("if", "", "Eingabe mit OGD-Spezifikation (Standard: stdin)")
var outputfile = flag.String("of", "", "Ausgabe der Spezifikation nach (Standard: stdout)")
var templateset = flag.String("ts", "", "(Satz von) Template-Dateien, die die Transformation der Spezifikation ins Ausgabeformat beschreibt")
var html = flag.Bool("html", true, "Anwendung von HTML-Escaping in der Ausgabe")
var printbuiltin = flag.Bool("printbuiltin", false, "Ausgabe von eingebautem Template (stdout)")
var help = flag.Bool("help", false, "Hilfe zur Verwendung")

type Templater interface {
	Execute(io.Writer, interface{}) error
}

func main() {
	flag.Parse()

	// Display help and exit
	if *help {
		flag.PrintDefaults()
		return
	}

	// Display default template and exit
	if *printbuiltin {
		fmt.Print(builtintpl)
		return
	}

	// If no input spec file is given, read from stdin
	if *inputfile == "" {
		*inputfile = os.Stdin.Name()
	}
	spec, err := ogdat.Loadogdatspec("unknown", *inputfile)
	if err != nil {
		log.Panicf("Could not load specification file %s, the error was %s\n", *inputfile, err)
	}

	var tpl Templater
	if *templateset != "" { // If a template set was given, try to read it
		if *html {
			tpl = htmltpl.Must(htmltpl.ParseFiles(*templateset))
		} else {
			tpl = texttpl.Must(texttpl.ParseFiles(*templateset))
		}
	} else { // otherwise use the built-in
		tpl = htmltpl.Must(htmltpl.New("").Parse(builtintpl))
	}

	// Open the output file
	var ofile *os.File
	if *outputfile == "" {
		ofile = os.Stdout
	} else {
		var err error
		// Do not overwrite an exisiting file but fail
		ofile, err = os.OpenFile(*outputfile, os.O_RDWR|os.O_CREATE|os.O_EXCL, os.FileMode(0666))
		if err != nil {
			log.Panicf("Can't open file %s for writing, the error was: %s\n", inputfile, err)
		}
		defer ofile.Close()
	}
	if err := tpl.Execute(ofile, spec); err != nil {
		log.Panicf("Template execution failed: %s\n", err)
	}
	log.Printf("Sepcification successfully transformed\n")
}

const builtintpl = `
<!DOCTYPE html>

<title></title>
<meta charset="UTF-8">

{{range .Beschreibung}}

{{.Bezeichner}} - {{if .IsRequired}}Pflichtfeld{{else}}optionaler Eintrag{{end}}

      {{index $.Label 0}}
      {{index $.Label 1}}
      {{index $.Label 2}}
      {{index $.Label 3}}
      {{index $.Label 4}}

      {{.ID}}
      {{.Bezeichner}}
      {{.OGD_Kurzname}}
      {{.CKAN_Feld}}
      {{.Anzahl}}

      {{index $.Label 5}}
      {{.Definition_DE}}

      {{index $.Label 6}}
      {{.Erlauterung}}

      {{index $.Label 7}}
      {{.Beispiel}}

      {{index $.Label 8}}
      {{.ONA2270}}

      {{index $.Label 9}}
      {{.ISO19115}}

      {{index $.Label 10}}
      {{.RDFProperty}}

      {{index $.Label 11}}
      {{.Definition_EN}}

{{end}}

`
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func brainfuck(src string) []uint8 {
	tape := []uint8{0}
	tapeIndex := 0

	srcLength := len(src)

	for srcIndex := 0; srcIndex < srcLength; srcIndex++ {
		char := string(src[srcIndex])

		switch char {
		case ">":
			tapeIndex += 1
			if len(tape) <= tapeIndex {
				tape = append(tape, 0)
			}

		case "<":
			if tapeIndex > 0 {
				tapeIndex -= 1
			}

		case "+":
			tape[tapeIndex] += 1

		case "-":
			tape[tapeIndex] -= 1

		case ".":
			print(string(uint8(tape[tapeIndex])))

		case ",":
			b := make([]byte, 1)
			os.Stdin.Read(b)
			tape[tapeIndex] = b[0]

		case "[":
			if tape[tapeIndex] == 0 {
				depth := 1
				for depth > 0 {
					srcIndex++
					srcCharacter := string(src[srcIndex])
					if srcCharacter == "[" {
						depth++
					} else if srcCharacter == "]" {
						depth--
					}
				}
			}

		case "]":
			depth := 1
			for depth > 0 {
				srcIndex--
				srcCharacter := string(src[srcIndex])
				if srcCharacter == "[" {
					depth--
				} else if srcCharacter == "]" {
					depth++
				}
			}
			srcIndex--
		}
	}

	return tape
}

func main() {
	content, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		fmt.Println("Error reading file")
		fmt.Println(err)
	} else {
		var src = string(content)

		brainfuck(src)
	}
}
<commit_msg>no string conversion, use runes. ditch var char.<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func brainfuck(src string) []uint8 {
	tape := []uint8{0}
	tapeIndex := 0

	srcLength := len(src)

	for srcIndex := 0; srcIndex < srcLength; srcIndex++ {

		switch src[srcIndex] {
		case '>':
			tapeIndex += 1
			if len(tape) <= tapeIndex {
				tape = append(tape, 0)
			}

		case '<':
			if tapeIndex > 0 {
				tapeIndex -= 1
			}

		case '+':
			tape[tapeIndex] += 1

		case '-':
			tape[tapeIndex] -= 1

		case '.':
			print(string(uint8(tape[tapeIndex])))

		case ',':
			b := make([]byte, 1)
			os.Stdin.Read(b)
			tape[tapeIndex] = b[0]

		case '[':
			if tape[tapeIndex] == 0 {
				depth := 1
				for depth > 0 {
					srcIndex++
					srcCharacter := string(src[srcIndex])
					if srcCharacter == "[" {
						depth++
					} else if srcCharacter == "]" {
						depth--
					}
				}
			}

		case ']':
			depth := 1
			for depth > 0 {
				srcIndex--
				srcCharacter := string(src[srcIndex])
				if srcCharacter == "[" {
					depth--
				} else if srcCharacter == "]" {
					depth++
				}
			}
			srcIndex--
		}
	}

	return tape
}

func main() {
	content, err := ioutil.ReadFile(os.Args[1])
	if err != nil {
		fmt.Println("Error reading file")
		fmt.Println(err)
	} else {
		var src = string(content)

		brainfuck(src)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 The nvim-go 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 nvimutil

import (
	"context"
	"time"

	"github.com/zchee/nvim-go/src/logger"
	"go.uber.org/zap"
)

// Profile measurement of the time it took to any func and output log file.
// Usage: defer nvim.Profile(time.Now(), "func name")
func Profile(ctx context.Context, start time.Time, name string) {
	elapsed := time.Since(start).Seconds()
	logger.FromContext(ctx).WithOptions(zap.AddCallerSkip(2)).Named("profile").Debug("elapsed", zap.Float64(name, elapsed))
}
<commit_msg>nvimutil: remove elapsed variable<commit_after>// Copyright 2016 The nvim-go 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 nvimutil

import (
	"context"
	"time"

	"github.com/zchee/nvim-go/src/logger"
	"go.uber.org/zap"
)

// Profile measurement of the time it took to any func and output log file.
// Usage: defer nvim.Profile(time.Now(), "func name")
func Profile(ctx context.Context, start time.Time, name string) {
	logger.FromContext(ctx).WithOptions(zap.AddCallerSkip(2)).Debug("profile: elapsed", zap.Float64(name, time.Since(start).Seconds()))
}
<|endoftext|>


<commit_before>package serial

import (
	"os"
	"testing"
)

const (
	// socat -d -d pty,raw,echo=0 pty,raw,echo=0
	pty1 = "/dev/pts/5"
	pty2 = "/dev/pts/6"
)

func TestReadWrite(t *testing.T) {
	checkPty(t)

	config1 := Config{Address: pty1}
	port1, err := Open(&config1)
	if err != nil {
		t.Fatal(err)
	}
	defer port1.Close()

	config2 := Config{
		Address:  pty2,
		BaudRate: 57600,
		DataBits: 7,
		Parity:   "N",
		StopBits: 2,
	}
	port2, err := Open(&config2)
	if err != nil {
		t.Fatal(err)
	}
	defer port2.Close()

	message := "test serial"
	n, err := port1.Write([]byte(message))
	if err != nil {
		t.Fatal(err)
	}
	if n != len(message) {
		t.Fatalf("unexpected write length %v", n)
	}
	var buf [16]byte
	n, err = port2.Read(buf[:])
	if err != nil {
		t.Fatal(err)
	}
	if string(buf[:n]) != message {
		t.Fatalf("unexpected response %q (len: %d)", buf[:n], n)
	}
}

func checkPty(t *testing.T) {
	for _, p := range [...]string{pty1, pty2} {
		if _, err := os.Stat(p); err != nil {
			t.Skipf("%v does not exist", p)
		}
	}
}
<commit_msg>changed pty endpoints in test code<commit_after>package serial

import (
	"os"
	"testing"
)

const (
	// socat -d -d pty,raw,echo=0 pty,raw,echo=0
	pty1 = "/dev/ttys009"
	pty2 = "/dev/ttys010"
)

func TestReadWrite(t *testing.T) {
	checkPty(t)

	config1 := Config{Address: pty1}
	port1, err := Open(&config1)
	if err != nil {
		t.Fatal(err)
	}
	defer port1.Close()

	config2 := Config{
		Address:  pty2,
		BaudRate: 57600,
		DataBits: 7,
		Parity:   "N",
		StopBits: 2,
	}
	port2, err := Open(&config2)
	if err != nil {
		t.Fatal(err)
	}
	defer port2.Close()

	message := "test serial"
	n, err := port1.Write([]byte(message))
	if err != nil {
		t.Fatal(err)
	}
	if n != len(message) {
		t.Fatalf("unexpected write length %v", n)
	}
	var buf [16]byte
	n, err = port2.Read(buf[:])
	if err != nil {
		t.Fatal(err)
	}
	if string(buf[:n]) != message {
		t.Fatalf("unexpected response %q (len: %d)", buf[:n], n)
	}
}

func checkPty(t *testing.T) {
	for _, p := range [...]string{pty1, pty2} {
		if _, err := os.Stat(p); err != nil {
			t.Skipf("%v does not exist", p)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
)

var ggcDir string
var port string

func ggcDirDefault() string {
	dir := "ggc"
	b, err := exec.Command("git", "config", "ghq.root").CombinedOutput()
	if err == nil {
		dir = string(b)
	}
	return dir
}

func main() {
	flag.Usage = func() {
		fmt.Printf(`Usage:
  ./ggc-server

Options:
`)
		flag.PrintDefaults()
	}

	var help bool

	flag.StringVar(&port, "port", "8080", "Port for listen")
	flag.StringVar(&ggcDir, "dir", ggcDirDefault(), "Directory to save repositories")
	flag.BoolVar(&help, "help", false, "Show help")
	flag.Parse()

	if help {
		flag.Usage()
		os.Exit(0)
	}

	ggcDir, err := filepath.Abs(ggcDir)
	if err != nil {
		log.Fatal(err)
	}

	if _, err := os.Stat(ggcDir); os.IsNotExist(err) {
		if err := os.MkdirAll(ggcDir, 0777); err != nil {
			log.Fatal(err)
		}
	}
	log.Printf("Accepting connections at http://localhost:%s/", port)
	log.Printf("Use base directory: %s", ggcDir)

	http.HandleFunc("/", gitClone)
	http.ListenAndServe(":"+port, nil)
}

func gitClone(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s %s %s", r.Proto, r.Method, r.URL, r.Header)

	if r.Method != "POST" {
		w.WriteHeader(404)
		fmt.Fprintf(w, "Not Found")
		return
	}

	host := r.FormValue("host")
	owner := r.FormValue("owner")
	repo := r.FormValue("repo")

	if host == "" || owner == "" || repo == "" {
		w.WriteHeader(400)
		fmt.Fprintf(w, "Bad Request")
		return
	}

	url := fmt.Sprintf("git@%s:%s/%s", host, owner, repo)
	reposPath := filepath.Join(ggcDir, host, owner, repo)
	cmd := exec.Command("git", "clone", url, reposPath)

	log.Printf("Repository: %s/%s/%s", host, owner, repo)

	cmd.Start()
}
<commit_msg>avoid multiple items of ghq.root.<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

var ggcDir string
var port string

func ggcDirDefault() string {
	dir := "ggc"
	b, err := exec.Command("git", "config", "ghq.root").CombinedOutput()
	if err == nil {
		if dirs := strings.Split(string(b), "\n"); len(dirs) > 0 {
			dir = strings.TrimSpace(dirs[0])
		}
	}
	return dir
}

func main() {
	flag.Usage = func() {
		fmt.Printf(`Usage:
  ./ggc-server

Options:
`)
		flag.PrintDefaults()
	}

	var help bool

	flag.StringVar(&port, "port", "8080", "Port for listen")
	flag.StringVar(&ggcDir, "dir", ggcDirDefault(), "Directory to save repositories")
	flag.BoolVar(&help, "help", false, "Show help")
	flag.Parse()

	if help {
		flag.Usage()
		os.Exit(0)
	}

	ggcDir, err := filepath.Abs(ggcDir)
	if err != nil {
		log.Fatal(err)
	}

	if _, err := os.Stat(ggcDir); os.IsNotExist(err) {
		if err := os.MkdirAll(ggcDir, 0777); err != nil {
			log.Fatal(err)
		}
	}
	log.Printf("Accepting connections at http://localhost:%s/", port)
	log.Printf("Use base directory: %s", ggcDir)

	http.HandleFunc("/", gitClone)
	http.ListenAndServe(":"+port, nil)
}

func gitClone(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s %s %s", r.Proto, r.Method, r.URL, r.Header)

	if r.Method != "POST" {
		w.WriteHeader(404)
		fmt.Fprintf(w, "Not Found")
		return
	}

	host := r.FormValue("host")
	owner := r.FormValue("owner")
	repo := r.FormValue("repo")

	if host == "" || owner == "" || repo == "" {
		w.WriteHeader(400)
		fmt.Fprintf(w, "Bad Request")
		return
	}

	url := fmt.Sprintf("git@%s:%s/%s", host, owner, repo)
	reposPath := filepath.Join(ggcDir, host, owner, repo)
	cmd := exec.Command("git", "clone", url, reposPath)

	log.Printf("Repository: %s/%s/%s", host, owner, repo)

	cmd.Start()
}
<|endoftext|>


<commit_before>package projects

import "time"

const (
	// GetSoftwareListEndpoint is the path to the endpoint for retrieving a specific Software List
	GetSoftwareListEndpoint = "v1/project/getSBOM"
	// GetSoftwareListsEndpoint is the path to the endpoint for retrieving an organization's Software Lists
	GetSoftwareListsEndpoint = "v1/project/getSBOMs"
)

// SoftwareList represents a software list containing zero or more Component objects.
type SoftwareList struct {
	ID               string      `json:"id"`
	Name             string      `json:"name"`
	Version          string      `json:"version"`
	Supplier         string      `json:"supplier"`
	ContactName      string      `json:"contact_name"`
	ContactEmail     string      `json:"contact_email"`
	MonitorFrequency string      `json:"monitor_frequency"`
	Status           string      `json:"status"`
	CreatedAt        time.Time   `json:"created_at"`
	UpdatedAt        time.Time   `json:"updated_at"`
	DeletedAt        *time.Time  `json:"deleted_at"`
	EntryCount       int         `json:"entry_count"`
	Metrics          Metrics     `json:"metrics"`
	Entries          []Component `json:"entries"`
	TeamID           string      `json:"team_id"`
	OrgID            string      `json:"org_id"`
	RulesetID        string      `json:"ruleset_id"`
}

type Risk struct {
	Score  int `json:"score"`
	Scopes struct {
		Ecosystem   int `json:"ecosystem"`
		SupplyChain int `json:"supplyChain"`
		Software    int `json:"software"`
	} `json:"scopes"`
}

type Compliance struct {
	Passing int `json:"passing"`
	Failing int `json:"failing"`
}

type Resolution struct {
	Resolved          int `json:"resolved"`
	PartiallyResolved int `json:"partiallyResolved"`
	Unresolved        int `json:"unresolved"`
}

type Metrics struct {
	Risk       Risk       `json:"risk"`
	Compliance Compliance `json:"compliance"`
	Resolution Resolution `json:"resolution"`
}

type SoftwareInventorySummary struct {
	ID            string         `json:"id"`
	Organization  Metrics        `json:"organization"`
	SoftwareLists []SoftwareList `json:"softwareLists"`
}
<commit_msg>[DEV-1243] Software -> Technology in risk scopes<commit_after>package projects

import "time"

const (
	// GetSoftwareListEndpoint is the path to the endpoint for retrieving a specific Software List
	GetSoftwareListEndpoint = "v1/project/getSBOM"
	// GetSoftwareListsEndpoint is the path to the endpoint for retrieving an organization's Software Lists
	GetSoftwareListsEndpoint = "v1/project/getSBOMs"
)

// SoftwareList represents a software list containing zero or more Component objects.
type SoftwareList struct {
	ID               string      `json:"id"`
	Name             string      `json:"name"`
	Version          string      `json:"version"`
	Supplier         string      `json:"supplier"`
	ContactName      string      `json:"contact_name"`
	ContactEmail     string      `json:"contact_email"`
	MonitorFrequency string      `json:"monitor_frequency"`
	Status           string      `json:"status"`
	CreatedAt        time.Time   `json:"created_at"`
	UpdatedAt        time.Time   `json:"updated_at"`
	DeletedAt        *time.Time  `json:"deleted_at"`
	EntryCount       int         `json:"entry_count"`
	Metrics          Metrics     `json:"metrics"`
	Entries          []Component `json:"entries"`
	TeamID           string      `json:"team_id"`
	OrgID            string      `json:"org_id"`
	RulesetID        string      `json:"ruleset_id"`
}

type Risk struct {
	Score  int `json:"score"`
	Scopes struct {
		Ecosystem   int `json:"ecosystem"`
		SupplyChain int `json:"supplyChain"`
		Technology  int `json:"technology"`
	} `json:"scopes"`
}

type Compliance struct {
	Passing int `json:"passing"`
	Failing int `json:"failing"`
}

type Resolution struct {
	Resolved          int `json:"resolved"`
	PartiallyResolved int `json:"partiallyResolved"`
	Unresolved        int `json:"unresolved"`
}

type Metrics struct {
	Risk       Risk       `json:"risk"`
	Compliance Compliance `json:"compliance"`
	Resolution Resolution `json:"resolution"`
}

type SoftwareInventorySummary struct {
	ID            string         `json:"id"`
	Organization  Metrics        `json:"organization"`
	SoftwareLists []SoftwareList `json:"softwareLists"`
}
<|endoftext|>


<commit_before>// Copyright 2013 Joyent Inc.
// Licensed under the AGPLv3, see LICENCE file for details.

package joyent

import (
	"sync"

	"github.com/joyent/gosign/auth"

	"launchpad.net/juju-core/constraints"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/environs/imagemetadata"
	"launchpad.net/juju-core/environs/simplestreams"
	"launchpad.net/juju-core/environs/storage"
	"launchpad.net/juju-core/provider/common"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/state/api"
)

// This file contains the core of the Joyent Environ implementation.

type JoyentEnviron struct {
	name string

	// supportedArchitectures caches the architectures
	// for which images can be instantiated.
	supportedArchitectures []string

	// All mutating operations should lock the mutex. Non-mutating operations
	// should read all fields (other than name, which is immutable) from a
	// shallow copy taken with getSnapshot().
	// This advice is predicated on the goroutine-safety of the values of the
	// affected fields.
	lock    sync.Mutex
	ecfg    *environConfig
	creds   *auth.Credentials
	storage storage.Storage
	compute *joyentCompute
}

var _ environs.Environ = (*JoyentEnviron)(nil)

func NewEnviron(cfg *config.Config) (*JoyentEnviron, error) {
	env := new(JoyentEnviron)
	err := env.SetConfig(cfg)
	if err != nil {
		return nil, err
	}
	env.name = cfg.Name()
	env.creds = getCredentials(env)
	env.storage = NewStorage(env, "")
	env.compute = NewCompute(env)
	return env, nil
}

func (env *JoyentEnviron) SetName(envName string) {
	env.name = envName
}

func (env *JoyentEnviron) Name() string {
	return env.name
}

func (*JoyentEnviron) Provider() environs.EnvironProvider {
	return providerInstance
}

// SupportedArchitectures is specified on the EnvironCapability interface.
func (env *JoyentEnviron) SupportedArchitectures() ([]string, error) {
	env.lock.Lock()
	defer env.lock.Unlock()
	if env.supportedArchitectures != nil {
		return env.supportedArchitectures, nil
	}
	cfg := env.Ecfg()
	// Create a filter to get all images from our region and for the correct stream.
	cloudSpec := simplestreams.CloudSpec{
		Region:   cfg.Region(),
		Endpoint: cfg.SdcUrl(),
	}
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
		Stream:    cfg.ImageStream(),
	})
	var err error
	env.supportedArchitectures, err = common.SupportedArchitectures(env, imageConstraint)
	return env.supportedArchitectures, err
}

func (env *JoyentEnviron) SetConfig(cfg *config.Config) error {
	env.lock.Lock()
	defer env.lock.Unlock()
	ecfg, err := providerInstance.newConfig(cfg)
	if err != nil {
		return err
	}
	env.ecfg = ecfg
	return nil
}

func (env *JoyentEnviron) getSnapshot() *JoyentEnviron {
	env.lock.Lock()
	clone := *env
	env.lock.Unlock()
	clone.lock = sync.Mutex{}
	return &clone
}

func (env *JoyentEnviron) Config() *config.Config {
	return env.getSnapshot().ecfg.Config
}

func (env *JoyentEnviron) Storage() storage.Storage {
	return env.getSnapshot().storage
}

func (env *JoyentEnviron) PublicStorage() storage.StorageReader {
	return environs.EmptyStorage
}

func (env *JoyentEnviron) Bootstrap(ctx environs.BootstrapContext, cons constraints.Value) error {
	return common.Bootstrap(ctx, env, cons)
}

func (env *JoyentEnviron) StateInfo() (*state.Info, *api.Info, error) {
	return common.StateInfo(env)
}

func (env *JoyentEnviron) Destroy() error {
	return common.Destroy(env)
}

func (env *JoyentEnviron) Ecfg() *environConfig {
	return env.getSnapshot().ecfg
}

func (env *JoyentEnviron) Credentials() *auth.Credentials {
	return env.getSnapshot().creds
}

func (env *JoyentEnviron) SetCredentials() {
	env.creds = getCredentials(env)
}

func getCredentials(env *JoyentEnviron) *auth.Credentials {
	authentication := auth.Auth{User: env.ecfg.mantaUser(), KeyFile: env.ecfg.keyFile(), Algorithm: env.ecfg.algorithm()}

	return &auth.Credentials{
		UserAuthentication: authentication,
		MantaKeyId:         env.ecfg.mantaKeyId(),
		MantaEndpoint:      auth.Endpoint{URL: env.ecfg.mantaUrl()},
		SdcKeyId:           env.ecfg.sdcKeyId(),
		SdcEndpoint:        auth.Endpoint{URL: env.ecfg.sdcUrl()},
	}
}

// MetadataLookupParams returns parameters which are used to query simplestreams metadata.
func (env *JoyentEnviron) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) {
	if region == "" {
		region = env.Ecfg().Region()
	}
	return &simplestreams.MetadataLookupParams{
		Series:        env.Ecfg().DefaultSeries(),
		Region:        region,
		Endpoint:      env.Ecfg().sdcUrl(),
		Architectures: []string{"amd64", "arm"},
	}, nil
}

// Region is specified in the HasRegion interface.
func (env *JoyentEnviron) Region() (simplestreams.CloudSpec, error) {
	return simplestreams.CloudSpec{
		Region:   env.Ecfg().Region(),
		Endpoint: env.Ecfg().sdcUrl(),
	}, nil
}

// GetImageSources returns a list of sources which are used to search for simplestreams image metadata.
func (env *JoyentEnviron) GetImageSources() ([]simplestreams.DataSource, error) {
	// Add the simplestreams source off the control bucket.
	sources := []simplestreams.DataSource{
		storage.NewStorageSimpleStreamsDataSource("cloud storage", env.Storage(), storage.BaseImagesPath)}
	return sources, nil
}

// GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata.
func (env *JoyentEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
	// Add the simplestreams source off the control bucket.
	sources := []simplestreams.DataSource{
		storage.NewStorageSimpleStreamsDataSource("cloud storage", env.Storage(), storage.BaseToolsPath)}
	return sources, nil
}
<commit_msg>Fix supported arch deadlock<commit_after>// Copyright 2013 Joyent Inc.
// Licensed under the AGPLv3, see LICENCE file for details.

package joyent

import (
	"sync"

	"github.com/joyent/gosign/auth"

	"launchpad.net/juju-core/constraints"
	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/environs/config"
	"launchpad.net/juju-core/environs/imagemetadata"
	"launchpad.net/juju-core/environs/simplestreams"
	"launchpad.net/juju-core/environs/storage"
	"launchpad.net/juju-core/provider/common"
	"launchpad.net/juju-core/state"
	"launchpad.net/juju-core/state/api"
)

// This file contains the core of the Joyent Environ implementation.

type JoyentEnviron struct {
	name string

	// supportedArchitectures caches the architectures
	// for which images can be instantiated.
	archLock               sync.Mutex
	supportedArchitectures []string

	// All mutating operations should lock the mutex. Non-mutating operations
	// should read all fields (other than name, which is immutable) from a
	// shallow copy taken with getSnapshot().
	// This advice is predicated on the goroutine-safety of the values of the
	// affected fields.
	lock    sync.Mutex
	ecfg    *environConfig
	creds   *auth.Credentials
	storage storage.Storage
	compute *joyentCompute
}

var _ environs.Environ = (*JoyentEnviron)(nil)

func NewEnviron(cfg *config.Config) (*JoyentEnviron, error) {
	env := new(JoyentEnviron)
	err := env.SetConfig(cfg)
	if err != nil {
		return nil, err
	}
	env.name = cfg.Name()
	env.creds = getCredentials(env)
	env.storage = NewStorage(env, "")
	env.compute = NewCompute(env)
	return env, nil
}

func (env *JoyentEnviron) SetName(envName string) {
	env.name = envName
}

func (env *JoyentEnviron) Name() string {
	return env.name
}

func (*JoyentEnviron) Provider() environs.EnvironProvider {
	return providerInstance
}

// SupportedArchitectures is specified on the EnvironCapability interface.
func (env *JoyentEnviron) SupportedArchitectures() ([]string, error) {
	env.archLock.Lock()
	defer env.archLock.Unlock()
	if env.supportedArchitectures != nil {
		return env.supportedArchitectures, nil
	}
	cfg := env.Ecfg()
	// Create a filter to get all images from our region and for the correct stream.
	cloudSpec := simplestreams.CloudSpec{
		Region:   cfg.Region(),
		Endpoint: cfg.SdcUrl(),
	}
	imageConstraint := imagemetadata.NewImageConstraint(simplestreams.LookupParams{
		CloudSpec: cloudSpec,
		Stream:    cfg.ImageStream(),
	})
	var err error
	env.supportedArchitectures, err = common.SupportedArchitectures(env, imageConstraint)
	return env.supportedArchitectures, err
}

func (env *JoyentEnviron) SetConfig(cfg *config.Config) error {
	env.lock.Lock()
	defer env.lock.Unlock()
	ecfg, err := providerInstance.newConfig(cfg)
	if err != nil {
		return err
	}
	env.ecfg = ecfg
	return nil
}

func (env *JoyentEnviron) getSnapshot() *JoyentEnviron {
	env.lock.Lock()
	clone := *env
	env.lock.Unlock()
	clone.lock = sync.Mutex{}
	return &clone
}

func (env *JoyentEnviron) Config() *config.Config {
	return env.getSnapshot().ecfg.Config
}

func (env *JoyentEnviron) Storage() storage.Storage {
	return env.getSnapshot().storage
}

func (env *JoyentEnviron) PublicStorage() storage.StorageReader {
	return environs.EmptyStorage
}

func (env *JoyentEnviron) Bootstrap(ctx environs.BootstrapContext, cons constraints.Value) error {
	return common.Bootstrap(ctx, env, cons)
}

func (env *JoyentEnviron) StateInfo() (*state.Info, *api.Info, error) {
	return common.StateInfo(env)
}

func (env *JoyentEnviron) Destroy() error {
	return common.Destroy(env)
}

func (env *JoyentEnviron) Ecfg() *environConfig {
	return env.getSnapshot().ecfg
}

func (env *JoyentEnviron) Credentials() *auth.Credentials {
	return env.getSnapshot().creds
}

func (env *JoyentEnviron) SetCredentials() {
	env.creds = getCredentials(env)
}

func getCredentials(env *JoyentEnviron) *auth.Credentials {
	authentication := auth.Auth{User: env.ecfg.mantaUser(), KeyFile: env.ecfg.keyFile(), Algorithm: env.ecfg.algorithm()}

	return &auth.Credentials{
		UserAuthentication: authentication,
		MantaKeyId:         env.ecfg.mantaKeyId(),
		MantaEndpoint:      auth.Endpoint{URL: env.ecfg.mantaUrl()},
		SdcKeyId:           env.ecfg.sdcKeyId(),
		SdcEndpoint:        auth.Endpoint{URL: env.ecfg.sdcUrl()},
	}
}

// MetadataLookupParams returns parameters which are used to query simplestreams metadata.
func (env *JoyentEnviron) MetadataLookupParams(region string) (*simplestreams.MetadataLookupParams, error) {
	if region == "" {
		region = env.Ecfg().Region()
	}
	return &simplestreams.MetadataLookupParams{
		Series:        env.Ecfg().DefaultSeries(),
		Region:        region,
		Endpoint:      env.Ecfg().sdcUrl(),
		Architectures: []string{"amd64", "arm"},
	}, nil
}

// Region is specified in the HasRegion interface.
func (env *JoyentEnviron) Region() (simplestreams.CloudSpec, error) {
	return simplestreams.CloudSpec{
		Region:   env.Ecfg().Region(),
		Endpoint: env.Ecfg().sdcUrl(),
	}, nil
}

// GetImageSources returns a list of sources which are used to search for simplestreams image metadata.
func (env *JoyentEnviron) GetImageSources() ([]simplestreams.DataSource, error) {
	// Add the simplestreams source off the control bucket.
	sources := []simplestreams.DataSource{
		storage.NewStorageSimpleStreamsDataSource("cloud storage", env.Storage(), storage.BaseImagesPath)}
	return sources, nil
}

// GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata.
func (env *JoyentEnviron) GetToolsSources() ([]simplestreams.DataSource, error) {
	// Add the simplestreams source off the control bucket.
	sources := []simplestreams.DataSource{
		storage.NewStorageSimpleStreamsDataSource("cloud storage", env.Storage(), storage.BaseToolsPath)}
	return sources, nil
}
<|endoftext|>


<commit_before>// Package gitlab implements the OAuth2 protocol for authenticating users through gitlab.
// This package can be used as a reference implementation of an OAuth2 provider for Goth.
package gitlab

import (
	"bytes"
	"encoding/json"
	"github.com/markbates/goth"
	"golang.org/x/oauth2"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
)

const (
	authURL         string = "https://gitlab.com/oauth/authorize"
	tokenURL        string = "https://gitlab.com/oauth/token"
	endpointProfile string = "https://gitlab.com/api/v3/user"
)

// Provider is the implementation of `goth.Provider` for accessing Gitlab.
type Provider struct {
	ClientKey   string
	Secret      string
	CallbackURL string
	config      *oauth2.Config
}

// New creates a new Gitlab provider and sets up important connection details.
// You should always call `gitlab.New` to get a new provider.  Never try to
// create one manually.
func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
	p := &Provider{
		ClientKey:   clientKey,
		Secret:      secret,
		CallbackURL: callbackURL,
	}
	p.config = newConfig(p, scopes)
	return p
}

// Name is the name used to retrieve this provider later.
func (p *Provider) Name() string {
	return "gitlab"
}

// Debug is a no-op for the gitlab package.
func (p *Provider) Debug(debug bool) {}

// BeginAuth asks Gitlab for an authentication end-point.
func (p *Provider) BeginAuth(state string) (goth.Session, error) {
	return &Session{
		AuthURL: p.config.AuthCodeURL(state),
	}, nil
}

// FetchUser will go to Gitlab and access basic information about the user.
func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
	sess := session.(*Session)
	user := goth.User{
		AccessToken:  sess.AccessToken,
		Provider:     p.Name(),
		RefreshToken: sess.RefreshToken,
		ExpiresAt:    sess.ExpiresAt,
	}

	response, err := http.Get(endpointProfile + "?access_token=" + url.QueryEscape(sess.AccessToken))
	if err != nil {
		if response != nil {
			response.Body.Close()
		}
		return user, err
	}

	defer response.Body.Close()

	bits, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return user, err
	}

	err = json.NewDecoder(bytes.NewReader(bits)).Decode(&user.RawData)
	if err != nil {
		return user, err
	}

	err = userFromReader(bytes.NewReader(bits), &user)

	return user, err
}

func newConfig(provider *Provider, scopes []string) *oauth2.Config {
	c := &oauth2.Config{
		ClientID:     provider.ClientKey,
		ClientSecret: provider.Secret,
		RedirectURL:  provider.CallbackURL,
		Endpoint: oauth2.Endpoint{
			AuthURL:  authURL,
			TokenURL: tokenURL,
		},
		Scopes: []string{},
	}

	if len(scopes) > 0 {
		for _, scope := range scopes {
			c.Scopes = append(c.Scopes, scope)
		}
	}
	return c
}

func userFromReader(r io.Reader, user *goth.User) error {
	u := struct {
		Name      string `json:"name"`
		Email     string `json:"email"`
		NickName  string `json:"username"`
		ID        int    `json:"id"`
		AvatarURL string `json:"avatar_url"`
	}{}
	err := json.NewDecoder(r).Decode(&u)
	if err != nil {
		return err
	}
	user.Email = u.Email
	user.Name = u.Name
	user.NickName = u.NickName
	user.UserID = strconv.Itoa(u.ID)
	user.AvatarURL = u.AvatarURL
	return nil
}

//RefreshTokenAvailable refresh token is provided by auth provider or not
func (p *Provider) RefreshTokenAvailable() bool {
	return true
}

//RefreshToken get new access token based on the refresh token
func (p *Provider) RefreshToken(refreshToken string) (*oauth2.Token, error) {
	token := &oauth2.Token{RefreshToken: refreshToken}
	ts := p.config.TokenSource(oauth2.NoContext, token)
	newToken, err := ts.Token()
	if err != nil {
		return nil, err
	}
	return newToken, err
}
<commit_msg>allow gitlab urls to be configurable<commit_after>// Package gitlab implements the OAuth2 protocol for authenticating users through gitlab.
// This package can be used as a reference implementation of an OAuth2 provider for Goth.
package gitlab

import (
	"bytes"
	"encoding/json"
	"github.com/markbates/goth"
	"golang.org/x/oauth2"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
)

// These vars define the Authentication, Token, and Profile URLS for Gitlab. If
// using Gitlab CE or EE, you should change these values before calling New.
//
// Examples:
//	gitlab.AuthURL = "https://gitlab.acme.com/oauth/authorize
//	gitlab.TokenURL = "https://gitlab.acme.com/oauth/token
//	gitlab.ProfileURL = "https://gitlab.acme.com/api/v3/user
var (
	AuthURL    = "https://gitlab.com/oauth/authorize"
	TokenURL   = "https://gitlab.com/oauth/token"
	ProfileURL = "https://gitlab.com/api/v3/user"
)

// Provider is the implementation of `goth.Provider` for accessing Gitlab.
type Provider struct {
	ClientKey   string
	Secret      string
	CallbackURL string
	config      *oauth2.Config
}

// New creates a new Gitlab provider and sets up important connection details.
// You should always call `gitlab.New` to get a new provider.  Never try to
// create one manually.
func New(clientKey, secret, callbackURL string, scopes ...string) *Provider {
	p := &Provider{
		ClientKey:   clientKey,
		Secret:      secret,
		CallbackURL: callbackURL,
	}
	p.config = newConfig(p, scopes)
	return p
}

// Name is the name used to retrieve this provider later.
func (p *Provider) Name() string {
	return "gitlab"
}

// Debug is a no-op for the gitlab package.
func (p *Provider) Debug(debug bool) {}

// BeginAuth asks Gitlab for an authentication end-point.
func (p *Provider) BeginAuth(state string) (goth.Session, error) {
	return &Session{
		AuthURL: p.config.AuthCodeURL(state),
	}, nil
}

// FetchUser will go to Gitlab and access basic information about the user.
func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
	sess := session.(*Session)
	user := goth.User{
		AccessToken:  sess.AccessToken,
		Provider:     p.Name(),
		RefreshToken: sess.RefreshToken,
		ExpiresAt:    sess.ExpiresAt,
	}

	response, err := http.Get(ProfileURL + "?access_token=" + url.QueryEscape(sess.AccessToken))
	if err != nil {
		if response != nil {
			response.Body.Close()
		}
		return user, err
	}

	defer response.Body.Close()

	bits, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return user, err
	}

	err = json.NewDecoder(bytes.NewReader(bits)).Decode(&user.RawData)
	if err != nil {
		return user, err
	}

	err = userFromReader(bytes.NewReader(bits), &user)

	return user, err
}

func newConfig(provider *Provider, scopes []string) *oauth2.Config {
	c := &oauth2.Config{
		ClientID:     provider.ClientKey,
		ClientSecret: provider.Secret,
		RedirectURL:  provider.CallbackURL,
		Endpoint: oauth2.Endpoint{
			AuthURL:  AuthURL,
			TokenURL: TokenURL,
		},
		Scopes: []string{},
	}

	if len(scopes) > 0 {
		for _, scope := range scopes {
			c.Scopes = append(c.Scopes, scope)
		}
	}
	return c
}

func userFromReader(r io.Reader, user *goth.User) error {
	u := struct {
		Name      string `json:"name"`
		Email     string `json:"email"`
		NickName  string `json:"username"`
		ID        int    `json:"id"`
		AvatarURL string `json:"avatar_url"`
	}{}
	err := json.NewDecoder(r).Decode(&u)
	if err != nil {
		return err
	}
	user.Email = u.Email
	user.Name = u.Name
	user.NickName = u.NickName
	user.UserID = strconv.Itoa(u.ID)
	user.AvatarURL = u.AvatarURL
	return nil
}

//RefreshTokenAvailable refresh token is provided by auth provider or not
func (p *Provider) RefreshTokenAvailable() bool {
	return true
}

//RefreshToken get new access token based on the refresh token
func (p *Provider) RefreshToken(refreshToken string) (*oauth2.Token, error) {
	token := &oauth2.Token{RefreshToken: refreshToken}
	ts := p.config.TokenSource(oauth2.NoContext, token)
	newToken, err := ts.Token()
	if err != nil {
		return nil, err
	}
	return newToken, err
}
<|endoftext|>