<commit_before>package fire

import (
	"context"
	"encoding/json"
	"io"
	"net/http"
	"reflect"

	"github.com/256dpi/jsonapi/v2"
	"github.com/256dpi/xo"
	"go.mongodb.org/mongo-driver/bson"

	"github.com/256dpi/fire/coal"
	"github.com/256dpi/fire/stick"
)

// An Operation indicates the purpose of a yield to a callback in the processing
// flow of an API request by a controller. These operations may occur multiple
// times during a single request.
type Operation int

// All the available operations.
const (
	// List operation will be used to authorize the loading of multiple
	// resources from a collection.
	//
	// Note: This operation is also used to load related resources.
	List Operation = 1 << iota

	// Find operation will be used to authorize the loading of a specific
	// resource from a collection.
	//
	// Note: This operation is also used to load a specific related resource.
	Find

	// Create operation will be used to authorize and validate the creation
	// of a new resource in a collection.
	Create

	// Update operation will be used to authorize the loading and validate
	// the updating of a specific resource in a collection.
	//
	// Note: Updates can include attributes, relationships or both.
	Update

	// Delete operation will be used to authorize the loading and validate
	// the deletion of a specific resource in a collection.
	Delete

	// CollectionAction operation will be used to authorize the execution
	// of a callback for a collection action.
	CollectionAction

	// ResourceAction operation will be used to authorize the execution of a
	// callback for a resource action.
	ResourceAction
)

// Read will return true when the operations only reads data.
func (o Operation) Read() bool {
	return o == List || o == Find
}

// Write will return true when the operation writes data.
func (o Operation) Write() bool {
	return o == Create || o == Update || o == Delete
}

// Action will return true when the operation is a collection or resource action.
func (o Operation) Action() bool {
	return o == CollectionAction || o == ResourceAction
}

// String returns the name of the operation.
func (o Operation) String() string {
	switch o {
	case List:
		return "List"
	case Find:
		return "Find"
	case Create:
		return "Create"
	case Update:
		return "Update"
	case Delete:
		return "Delete"
	case CollectionAction:
		return "CollectionAction"
	case ResourceAction:
		return "ResourceAction"
	}

	return ""
}

// Context carries the state of a request and allows callbacks to influence the
// processing of a request.
type Context struct {
	// The context that is cancelled when the timeout has been exceeded or the
	// underlying connection transport has been closed. It may also carry the
	// database session if a transaction is used.
	//
	// Values: lungo.ISessionContext?, trace.Span, *xo.Tracer
	context.Context

	// The custom data map.
	Data stick.Map

	// The current callback stage.
	Stage Stage

	// The deferred callbacks.
	Defers map[Stage][]*Callback

	// The current operation in process.
	//
	// Usage: Read only
	// Availability: Authorizers
	Operation Operation

	// The query that will be used during a List, Find, Update, Delete or
	// ResourceAction operation to select a list of models or a specific model.
	//
	// On Find, Update and Delete operations, the "_id" key is preset to the
	// resource id, while on forwarded List operations the relationship filter
	// is preset.
	//
	// Usage: Read only
	// Availability: Authorizers
	// Operations: !Create, !CollectionAction
	Selector bson.M

	// The filters that will be used during a List, Find, Update, Delete or
	// ResourceAction operation to further filter the selection of a list of
	// models or a specific model.
	//
	// On List operations, attribute and relationship filters are preset.
	//
	// Usage: Append only
	// Availability: Authorizers
	// Operations: !Create, !CollectionAction
	Filters []bson.M

	// The sorting that will be used during List.
	//
	// Usage: No Restriction
	// Availability: Authorizers
	// Operations: List
	Sorting []string

	// Only the whitelisted readable fields are exposed to the client as
	// attributes and relationships. Additionally, only readable fields can
	// be used for filtering and sorting.
	//
	// Usage: Reduce only
	// Availability: Authorizers
	// Operations: !Delete, !ResourceAction, !CollectionAction
	ReadableFields []string

	// Used instead of ReadableFields if set. Allows specifying readable fields
	// on a per model basis. The provided model may be nil if run before any
	// model has been loaded. Must be a subset of ReadableFields.
	GetReadableFields func(coal.Model) []string

	// Only the whitelisted writable fields can be altered by requests.
	//
	// Usage: Reduce only
	// Availability: Authorizers
	// Operations: Create, Update
	WritableFields []string

	// Used instead of WritableFields if set. Allows specifying writable fields
	// on a per model basis. Must be a subset of WritableFields.
	GetWritableFields func(coal.Model) []string

	// Only the whitelisted readable properties are exposed to the client as
	// attributes.
	//
	// Usage: Reduce only
	// Availability: Authorizers
	// Operations: !Delete, !ResourceActon, !CollectionAction
	ReadableProperties []string

	// Used instead of ReadableProperties if set. Allows specifying readable
	// properties on a per model basis. Must be a subset of ReadableProperties.
	GetReadableProperties func(coal.Model) []string

	// The filters that will be applied when loading has one and has many
	// relationships.
	//
	// Usage: Append only
	// Availability: Authorizers.
	// Operations: !Create, !CollectionAction
	RelationshipFilters map[string][]bson.M

	// The model that will be created, updated, deleted or is requested by a
	// resource action.
	//
	// Usage: Modify only
	// Availability: Validators
	// Operations: Create, Update, Delete, ResourceAction
	Model coal.Model

	// The models that will be returned for a List operation.
	//
	// Usage: Modify only
	// Availability: Decorators
	// Operations: List
	Models []coal.Model

	// The original model that is being updated. Can be used to lookup up
	// original values of changed fields.
	//
	// Usage: Ready only
	// Availability: Validators
	// Operations: Update
	Original coal.Model

	// The document that has been received by the client.
	//
	// Usage: Read only
	// Availability: Authorizers
	// Operations: !List, !Find, !CollectionAction, !ResourceAction
	Request *jsonapi.Document

	// The document that will be written to the client.
	//
	// Usage: Modify only
	// Availability: Notifiers
	// Operations: !CollectionAction, !ResourceAction
	Response *jsonapi.Document

	// The status code that will be written to the client.
	//
	// Usage: Modify only
	// Availability: Notifiers
	// Operations: !CollectionAction, !ResourceAction
	ResponseCode int

	// The store that is used to retrieve and persist the model.
	//
	// Usage: Read only
	Store *coal.Store

	// The underlying JSON-API request.
	//
	// Usage: Read only
	JSONAPIRequest *jsonapi.Request

	// The underlying HTTP request.
	//
	// Note: The path is not updated when a controller forwards a request to
	// a related controller.
	//
	// Usage: Read only
	HTTPRequest *http.Request

	// The underlying HTTP response writer. The response writer should only be
	// used during collection or resource actions to write a custom response.
	//
	// Usage: Read only
	ResponseWriter http.ResponseWriter

	// The controller that is managing the request.
	//
	// Usage: Read only
	Controller *Controller

	// The group that received the request.
	//
	// Usage: Read only
	Group *Group

	// The current tracer.
	//
	// Usage: Read only
	Tracer *xo.Tracer
}

// With will run the provided function with the specified context temporarily
// set on the context. This is especially useful together with transactions.
func (c *Context) With(ctx context.Context, fn func()) {
	// retain current context and tracer
	oc := c.Context
	ot := c.Tracer

	// swap tracer and context
	if c.Tracer != nil {
		c.Tracer, c.Context = xo.NewTracer(ctx)
	} else {
		c.Context = ctx
	}

	// yield
	fn()

	// switchback
	c.Context = oc
	c.Tracer = ot
}

// Defer will defer the provided handler and run it after all controller
// callbacks have been run at the specified stages.
func (c *Context) Defer(cb *Callback) {
	// check stage
	if cb.Stage <= c.Stage {
		panic("fire: invalid stage")
	}

	// ensure map
	if c.Defers == nil {
		c.Defers = map[Stage][]*Callback{}
	}

	// add callback for all stages
	for _, stage := range cb.Stage.Split() {
		c.Defers[stage] = append(c.Defers[stage], cb)
	}
}

// Query returns the composite query of Selector and Filter.
func (c *Context) Query() bson.M {
	// prepare sub queries
	var subQueries []bson.M

	// add selector if present
	if len(c.Selector) > 0 {
		subQueries = append(subQueries, c.Selector)
	}

	// add filters
	subQueries = append(subQueries, c.Filters...)

	// return empty query if no sub queries are present
	if len(subQueries) == 0 {
		return bson.M{}
	}

	// otherwise, return $and query
	return bson.M{"$and": subQueries}
}

// Modified will return whether the specified field has been changed. During an
// update operation the modification is checked against the original model. For
// all other operations, the field is checked against its zero value.
func (c *Context) Modified(field string) bool {
	// determine old value
	var oldValue interface{}
	if c.Original != nil {
		oldValue = stick.MustGet(c.Original, field)
	} else {
		oldValue = reflect.Zero(coal.GetMeta(c.Model).Fields[field].Type).Interface()
	}

	// get new value
	newValue := stick.MustGet(c.Model, field)

	return !reflect.DeepEqual(newValue, oldValue)
}

// Parse will decode a custom JSON body to the specified value.
func (c *Context) Parse(value interface{}) error {
	// unmarshal json
	err := json.NewDecoder(c.HTTPRequest.Body).Decode(value)
	if err == io.EOF {
		return xo.SF("incomplete request body")
	} else if err != nil {
		return xo.W(err)
	}

	return nil
}

// Respond will encode the provided value as JSON and write it to the client.
func (c *Context) Respond(value interface{}) error {
	// encode response
	bytes, err := json.Marshal(value)
	if err != nil {
		return xo.W(err)
	}

	// write token
	_, err = c.ResponseWriter.Write(bytes)
	if err != nil {
		return xo.W(err)
	}

	return nil
}
<commit_msg>updated docs<commit_after>package fire

import (
	"context"
	"encoding/json"
	"io"
	"net/http"
	"reflect"

	"github.com/256dpi/jsonapi/v2"
	"github.com/256dpi/xo"
	"go.mongodb.org/mongo-driver/bson"

	"github.com/256dpi/fire/coal"
	"github.com/256dpi/fire/stick"
)

// An Operation indicates the purpose of a yield to a callback in the processing
// flow of an API request by a controller. These operations may occur multiple
// times during a single request.
type Operation int

// All the available operations.
const (
	// List operation will be used to authorize the loading of multiple
	// resources from a collection.
	//
	// Note: This operation is also used to load related resources.
	List Operation = 1 << iota

	// Find operation will be used to authorize the loading of a specific
	// resource from a collection.
	//
	// Note: This operation is also used to load a specific related resource.
	Find

	// Create operation will be used to authorize and validate the creation
	// of a new resource in a collection.
	Create

	// Update operation will be used to authorize the loading and validate
	// the updating of a specific resource in a collection.
	//
	// Note: Updates can include attributes, relationships or both.
	Update

	// Delete operation will be used to authorize the loading and validate
	// the deletion of a specific resource in a collection.
	Delete

	// CollectionAction operation will be used to authorize the execution
	// of a callback for a collection action.
	CollectionAction

	// ResourceAction operation will be used to authorize the execution of a
	// callback for a resource action.
	ResourceAction
)

// Read will return true when the operations only reads data.
func (o Operation) Read() bool {
	return o == List || o == Find
}

// Write will return true when the operation writes data.
func (o Operation) Write() bool {
	return o == Create || o == Update || o == Delete
}

// Action will return true when the operation is a collection or resource action.
func (o Operation) Action() bool {
	return o == CollectionAction || o == ResourceAction
}

// String returns the name of the operation.
func (o Operation) String() string {
	switch o {
	case List:
		return "List"
	case Find:
		return "Find"
	case Create:
		return "Create"
	case Update:
		return "Update"
	case Delete:
		return "Delete"
	case CollectionAction:
		return "CollectionAction"
	case ResourceAction:
		return "ResourceAction"
	}

	return ""
}

// Context carries the state of a request and allows callbacks to influence the
// processing of a request.
type Context struct {
	// The context that is cancelled when the timeout has been exceeded or the
	// underlying connection transport has been closed. It may also carry the
	// database session if a transaction is used.
	//
	// Values: lungo.ISessionContext?, trace.Span, *xo.Tracer
	context.Context

	// The custom data map.
	Data stick.Map

	// The current callback stage.
	Stage Stage

	// The deferred callbacks.
	Defers map[Stage][]*Callback

	// The current operation in process.
	//
	// Usage: Read only
	// Availability: Authorizers
	Operation Operation

	// The query that will be used during a List, Find, Update, Delete or
	// ResourceAction operation to select a list of models or a specific model.
	//
	// On Find, Update and Delete operations, the "_id" key is preset to the
	// resource id, while on forwarded List operations the relationship filter
	// is preset.
	//
	// Usage: Read only
	// Availability: Authorizers
	// Operations: !Create, !CollectionAction
	Selector bson.M

	// The filters that will be used during a List, Find, Update, Delete or
	// ResourceAction operation to further filter the selection of a list of
	// models or a specific model.
	//
	// On List operations, attribute and relationship filters are preset.
	//
	// Usage: Append only
	// Availability: Authorizers
	// Operations: !Create, !CollectionAction
	Filters []bson.M

	// The sorting that will be used during List.
	//
	// Usage: No Restriction
	// Availability: Authorizers
	// Operations: List
	Sorting []string

	// Only the whitelisted readable fields are exposed to the client as
	// attributes and relationships. Additionally, only readable fields can
	// be used for filtering and sorting.
	//
	// Usage: Reduce only
	// Availability: Authorizers
	// Operations: !Delete, !ResourceAction, !CollectionAction
	ReadableFields []string

	// Used instead of ReadableFields if set. Allows specifying readable fields
	// on a per model basis. The model is nil during the initial load of fields
	// during a List operation. Returned list must be a subset of ReadableFields.
	GetReadableFields func(coal.Model) []string

	// Only the whitelisted writable fields can be altered by requests.
	//
	// Usage: Reduce only
	// Availability: Authorizers
	// Operations: Create, Update
	WritableFields []string

	// Used instead of WritableFields if set. Allows specifying writable fields
	// on a per model basis. The model is zero when getting the writable fields
	// during a Create operation. Returned list must be a subset of WritableFields.
	GetWritableFields func(coal.Model) []string

	// Only the whitelisted readable properties are exposed to the client as
	// attributes.
	//
	// Usage: Reduce only
	// Availability: Authorizers
	// Operations: !Delete, !ResourceActon, !CollectionAction
	ReadableProperties []string

	// Used instead of ReadableProperties if set. Allows specifying readable
	// properties on a per model basis. Returned list must be a subset of
	// ReadableProperties.
	GetReadableProperties func(coal.Model) []string

	// The filters that will be applied when loading has one and has many
	// relationships.
	//
	// Usage: Append only
	// Availability: Authorizers.
	// Operations: !Create, !CollectionAction
	RelationshipFilters map[string][]bson.M

	// The model that will be created, updated, deleted or is requested by a
	// resource action.
	//
	// Usage: Modify only
	// Availability: Validators
	// Operations: Create, Update, Delete, ResourceAction
	Model coal.Model

	// The models that will be returned for a List operation.
	//
	// Usage: Modify only
	// Availability: Decorators
	// Operations: List
	Models []coal.Model

	// The original model that is being updated. Can be used to lookup up
	// original values of changed fields.
	//
	// Usage: Ready only
	// Availability: Validators
	// Operations: Update
	Original coal.Model

	// The document that has been received by the client.
	//
	// Usage: Read only
	// Availability: Authorizers
	// Operations: !List, !Find, !CollectionAction, !ResourceAction
	Request *jsonapi.Document

	// The document that will be written to the client.
	//
	// Usage: Modify only
	// Availability: Notifiers
	// Operations: !CollectionAction, !ResourceAction
	Response *jsonapi.Document

	// The status code that will be written to the client.
	//
	// Usage: Modify only
	// Availability: Notifiers
	// Operations: !CollectionAction, !ResourceAction
	ResponseCode int

	// The store that is used to retrieve and persist the model.
	//
	// Usage: Read only
	Store *coal.Store

	// The underlying JSON-API request.
	//
	// Usage: Read only
	JSONAPIRequest *jsonapi.Request

	// The underlying HTTP request.
	//
	// Note: The path is not updated when a controller forwards a request to
	// a related controller.
	//
	// Usage: Read only
	HTTPRequest *http.Request

	// The underlying HTTP response writer. The response writer should only be
	// used during collection or resource actions to write a custom response.
	//
	// Usage: Read only
	ResponseWriter http.ResponseWriter

	// The controller that is managing the request.
	//
	// Usage: Read only
	Controller *Controller

	// The group that received the request.
	//
	// Usage: Read only
	Group *Group

	// The current tracer.
	//
	// Usage: Read only
	Tracer *xo.Tracer
}

// With will run the provided function with the specified context temporarily
// set on the context. This is especially useful together with transactions.
func (c *Context) With(ctx context.Context, fn func()) {
	// retain current context and tracer
	oc := c.Context
	ot := c.Tracer

	// swap tracer and context
	if c.Tracer != nil {
		c.Tracer, c.Context = xo.NewTracer(ctx)
	} else {
		c.Context = ctx
	}

	// yield
	fn()

	// switchback
	c.Context = oc
	c.Tracer = ot
}

// Defer will defer the provided handler and run it after all controller
// callbacks have been run at the specified stages.
func (c *Context) Defer(cb *Callback) {
	// check stage
	if cb.Stage <= c.Stage {
		panic("fire: invalid stage")
	}

	// ensure map
	if c.Defers == nil {
		c.Defers = map[Stage][]*Callback{}
	}

	// add callback for all stages
	for _, stage := range cb.Stage.Split() {
		c.Defers[stage] = append(c.Defers[stage], cb)
	}
}

// Query returns the composite query of Selector and Filter.
func (c *Context) Query() bson.M {
	// prepare sub queries
	var subQueries []bson.M

	// add selector if present
	if len(c.Selector) > 0 {
		subQueries = append(subQueries, c.Selector)
	}

	// add filters
	subQueries = append(subQueries, c.Filters...)

	// return empty query if no sub queries are present
	if len(subQueries) == 0 {
		return bson.M{}
	}

	// otherwise, return $and query
	return bson.M{"$and": subQueries}
}

// Modified will return whether the specified field has been changed. During an
// update operation the modification is checked against the original model. For
// all other operations, the field is checked against its zero value.
func (c *Context) Modified(field string) bool {
	// determine old value
	var oldValue interface{}
	if c.Original != nil {
		oldValue = stick.MustGet(c.Original, field)
	} else {
		oldValue = reflect.Zero(coal.GetMeta(c.Model).Fields[field].Type).Interface()
	}

	// get new value
	newValue := stick.MustGet(c.Model, field)

	return !reflect.DeepEqual(newValue, oldValue)
}

// Parse will decode a custom JSON body to the specified value.
func (c *Context) Parse(value interface{}) error {
	// unmarshal json
	err := json.NewDecoder(c.HTTPRequest.Body).Decode(value)
	if err == io.EOF {
		return xo.SF("incomplete request body")
	} else if err != nil {
		return xo.W(err)
	}

	return nil
}

// Respond will encode the provided value as JSON and write it to the client.
func (c *Context) Respond(value interface{}) error {
	// encode response
	bytes, err := json.Marshal(value)
	if err != nil {
		return xo.W(err)
	}

	// write token
	_, err = c.ResponseWriter.Write(bytes)
	if err != nil {
		return xo.W(err)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"go/format"
	"io"
	"os"
	"reflect"
	"sort"
	"strings"
	"unicode"
)

// Given a JSON string representation of an object and a name structName,
// attemp to generate a struct definition
func generate(input io.Reader, structName, pkgName string) ([]byte, error) {
	var iresult interface{}
	var result map[string]interface{}
	if err := json.NewDecoder(input).Decode(&iresult); err != nil {
		return nil, err
	}

	switch iresult := iresult.(type) {
	case map[string]interface{}:
		result = iresult
	case []map[string]interface{}:
		if len(iresult) > 0 {
			result = iresult[0]
		} else {
			return nil, fmt.Errorf("empty array")
		}
	default:
		return nil, fmt.Errorf("unexpected type: %T", iresult)
	}

	src := fmt.Sprintf("package %s\ntype %s %s}",
		pkgName,
		structName,
		generateTypes(result, 0))
	formatted, err := format.Source([]byte(src))
	if err != nil {
		err = fmt.Errorf("error formatting: %s, was formatting\n%s", err, src)
	}
	return formatted, err
}

// Generate go struct entries for a map[string]interface{} structure
func generateTypes(obj map[string]interface{}, depth int) string {
	structure := "struct {"

	keys := make([]string, 0, len(obj))
	for key := range obj {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	for _, key := range keys {
		value := obj[key]
		valueType := typeForValue(value)

		//If a nested value, recurse
		switch value := value.(type) {
		case []map[string]interface{}:
			valueType = "[]" + generateTypes(value[0], depth+1) + "}"
		case map[string]interface{}:
			valueType = generateTypes(value, depth+1) + "}"
		}

		fieldName := fmtFieldName(key)
		structure += fmt.Sprintf("\n%s %s `json:\"%s\"`",
			fieldName,
			valueType,
			key)
	}
	return structure
}

var uppercaseFixups = map[string]bool{"id": true, "url": true}

// fmtFieldName formats a string as a struct key
//
// Example:
// 	fmtFieldName("foo_id")
// Output: FooID
func fmtFieldName(s string) string {
	parts := strings.Split(s, "_")
	for i := range parts {
		parts[i] = strings.Title(parts[i])
	}
	if len(parts) > 0 {
		last := parts[len(parts)-1]
		if uppercaseFixups[strings.ToLower(last)] {
			parts[len(parts)-1] = strings.ToUpper(last)
		}
	}
	assembled := strings.Join(parts, "")
	runes := []rune(assembled)
	for i, c := range runes {
		ok := unicode.IsLetter(c) || unicode.IsDigit(c)
		if i == 0 {
			ok = unicode.IsLetter(c)
		}
		if !ok {
			runes[i] = '_'
		}
	}
	return string(runes)
}

// generate an appropriate struct type entry
func typeForValue(value interface{}) string {
	//Check if this is an array
	if objects, ok := value.([]interface{}); ok {
		types := make(map[reflect.Type]bool, 0)
		for _, o := range objects {
			types[reflect.TypeOf(o)] = true
		}
		if len(types) == 1 {
			return "[]" + typeForValue(objects[0])
		}
		return "[]interface{}"
	} else if object, ok := value.(map[string]interface{}); ok {
		return generateTypes(object, 0) + "}"
	} else if reflect.TypeOf(value) == nil {
		return "interface{}"
	}
	return reflect.TypeOf(value).Name()
}
<commit_msg>Fixed build error<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"go/format"
	"io"
	"reflect"
	"sort"
	"strings"
	"unicode"
)

// Given a JSON string representation of an object and a name structName,
// attemp to generate a struct definition
func generate(input io.Reader, structName, pkgName string) ([]byte, error) {
	var iresult interface{}
	var result map[string]interface{}
	if err := json.NewDecoder(input).Decode(&iresult); err != nil {
		return nil, err
	}

	switch iresult := iresult.(type) {
	case map[string]interface{}:
		result = iresult
	case []map[string]interface{}:
		if len(iresult) > 0 {
			result = iresult[0]
		} else {
			return nil, fmt.Errorf("empty array")
		}
	default:
		return nil, fmt.Errorf("unexpected type: %T", iresult)
	}

	src := fmt.Sprintf("package %s\ntype %s %s}",
		pkgName,
		structName,
		generateTypes(result, 0))
	formatted, err := format.Source([]byte(src))
	if err != nil {
		err = fmt.Errorf("error formatting: %s, was formatting\n%s", err, src)
	}
	return formatted, err
}

// Generate go struct entries for a map[string]interface{} structure
func generateTypes(obj map[string]interface{}, depth int) string {
	structure := "struct {"

	keys := make([]string, 0, len(obj))
	for key := range obj {
		keys = append(keys, key)
	}
	sort.Strings(keys)

	for _, key := range keys {
		value := obj[key]
		valueType := typeForValue(value)

		//If a nested value, recurse
		switch value := value.(type) {
		case []map[string]interface{}:
			valueType = "[]" + generateTypes(value[0], depth+1) + "}"
		case map[string]interface{}:
			valueType = generateTypes(value, depth+1) + "}"
		}

		fieldName := fmtFieldName(key)
		structure += fmt.Sprintf("\n%s %s `json:\"%s\"`",
			fieldName,
			valueType,
			key)
	}
	return structure
}

var uppercaseFixups = map[string]bool{"id": true, "url": true}

// fmtFieldName formats a string as a struct key
//
// Example:
// 	fmtFieldName("foo_id")
// Output: FooID
func fmtFieldName(s string) string {
	parts := strings.Split(s, "_")
	for i := range parts {
		parts[i] = strings.Title(parts[i])
	}
	if len(parts) > 0 {
		last := parts[len(parts)-1]
		if uppercaseFixups[strings.ToLower(last)] {
			parts[len(parts)-1] = strings.ToUpper(last)
		}
	}
	assembled := strings.Join(parts, "")
	runes := []rune(assembled)
	for i, c := range runes {
		ok := unicode.IsLetter(c) || unicode.IsDigit(c)
		if i == 0 {
			ok = unicode.IsLetter(c)
		}
		if !ok {
			runes[i] = '_'
		}
	}
	return string(runes)
}

// generate an appropriate struct type entry
func typeForValue(value interface{}) string {
	//Check if this is an array
	if objects, ok := value.([]interface{}); ok {
		types := make(map[reflect.Type]bool, 0)
		for _, o := range objects {
			types[reflect.TypeOf(o)] = true
		}
		if len(types) == 1 {
			return "[]" + typeForValue(objects[0])
		}
		return "[]interface{}"
	} else if object, ok := value.(map[string]interface{}); ok {
		return generateTypes(object, 0) + "}"
	} else if reflect.TypeOf(value) == nil {
		return "interface{}"
	}
	return reflect.TypeOf(value).Name()
}
<|endoftext|>


<commit_before>package libhyperstart

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"syscall"
	"time"

	hyperstartgrpc "github.com/hyperhq/runv/hyperstart/api/grpc"
	hyperstartjson "github.com/hyperhq/runv/hyperstart/api/json"
	"google.golang.org/grpc"
	"google.golang.org/grpc/grpclog"
)

type grpcBasedHyperstart struct {
	ctx  context.Context
	conn *grpc.ClientConn
	grpc hyperstartgrpc.HyperstartServiceClient
}

// NewGrpcBasedHyperstart create hyperstart interface with grpc protocol
func NewGrpcBasedHyperstart(hyperstartGRPCSock string) (Hyperstart, error) {
	grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags))
	dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithTimeout(5 * time.Second)}
	dialOpts = append(dialOpts,
		grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
			return net.DialTimeout("unix", addr, timeout)
		},
		))
	conn, err := grpc.Dial(hyperstartGRPCSock, dialOpts...)
	if err != nil {
		return nil, err
	}
	return &grpcBasedHyperstart{
		ctx:  context.Background(),
		conn: conn,
		grpc: hyperstartgrpc.NewHyperstartServiceClient(conn),
	}, nil
}

func (h *grpcBasedHyperstart) Close() {
	h.conn.Close()
}

func (h *grpcBasedHyperstart) LastStreamSeq() uint64 {
	return 0
}

func (h *grpcBasedHyperstart) APIVersion() (uint32, error) {
	return 4244, nil
}

func (h *grpcBasedHyperstart) PauseSync() error {
	// TODO:
	return nil
}

func (h *grpcBasedHyperstart) Unpause() error {
	// TODO:
	return nil
}

func (h *grpcBasedHyperstart) WriteFile(container, path string, data []byte) error {
	return fmt.Errorf("WriteFile() is unsupported on grpc based hyperstart API")
}

func (h *grpcBasedHyperstart) ReadFile(container, path string) ([]byte, error) {
	return nil, fmt.Errorf("ReadFile() is unsupported on grpc based hyperstart API")
}

func (h *grpcBasedHyperstart) AddRoute(routes []hyperstartjson.Route) error {
	req := &hyperstartgrpc.AddRouteRequest{}
	for _, r := range routes {
		req.Routes = append(req.Routes, &hyperstartgrpc.Route{
			Dest:    r.Dest,
			Gateway: r.Gateway,
			Device:  r.Device,
		})
	}
	_, err := h.grpc.AddRoute(h.ctx, req)
	return err
}

func (h *grpcBasedHyperstart) UpdateInterface(dev, ip, mask string) error {
	_, err := h.grpc.UpdateInterface(h.ctx, &hyperstartgrpc.UpdateInterfaceRequest{
		Device:  dev,
		Address: ip,
		Mask:    mask,
	})
	return err
}

func (h *grpcBasedHyperstart) WriteStdin(container, process string, data []byte) (int, error) {
	ret, err := h.grpc.WriteStdin(h.ctx, &hyperstartgrpc.WriteStreamRequest{
		Container: container,
		Process:   process,
		Data:      data,
	})
	if err == nil {
		return int(ret.Len), nil
	}
	// todo check if it is &grpc.rpcError{code:0xb, desc:"EOF"} and return io.EOF instead
	return 0, err
}

func (h *grpcBasedHyperstart) ReadStdout(container, process string, data []byte) (int, error) {
	ret, err := h.grpc.ReadStdout(h.ctx, &hyperstartgrpc.ReadStreamRequest{
		Container: container,
		Process:   process,
		Len:       uint32(len(data)),
	})
	if err == nil {
		copy(data, ret.Data)
		return len(ret.Data), nil
	}
	// todo check if it is &grpc.rpcError{code:0xb, desc:"EOF"} and return io.EOF instead
	return 0, err
}

func (h *grpcBasedHyperstart) ReadStderr(container, process string, data []byte) (int, error) {
	ret, err := h.grpc.ReadStderr(h.ctx, &hyperstartgrpc.ReadStreamRequest{
		Container: container,
		Process:   process,
		Len:       uint32(len(data)),
	})
	if err == nil {
		copy(data, ret.Data)
		return len(ret.Data), nil
	}
	// todo check if it is &grpc.rpcError{code:0xb, desc:"EOF"} and return io.EOF instead
	return 0, err
}

func (h *grpcBasedHyperstart) CloseStdin(container, process string) error {
	_, err := h.grpc.CloseStdin(h.ctx, &hyperstartgrpc.CloseStdinRequest{
		Container: container,
		Process:   process,
	})
	return err
}

func (h *grpcBasedHyperstart) TtyWinResize(container, process string, row, col uint16) error {
	_, err := h.grpc.TtyWinResize(h.ctx, &hyperstartgrpc.TtyWinResizeRequest{
		Container: container,
		Process:   process,
		Row:       uint32(row),
		Column:    uint32(col),
	})
	return err
}

func (h *grpcBasedHyperstart) OnlineCpuMem() error {
	_, err := h.grpc.OnlineCPUMem(h.ctx, &hyperstartgrpc.OnlineCPUMemRequest{})
	return err
}

func process4json2grpc(p *hyperstartjson.Process) *hyperstartgrpc.Process {
	envs := map[string]string{}
	for _, env := range p.Envs {
		envs[env.Env] = env.Value
	}
	return &hyperstartgrpc.Process{
		Id:       p.Id,
		User:     &hyperstartgrpc.User{Uid: p.User, Gid: p.Group},
		Terminal: p.Terminal,
		Envs:     envs,
		Args:     p.Args,
		Workdir:  p.Workdir,
	}
}

func container4json2grpc(c *hyperstartjson.Container) *hyperstartgrpc.Container {
	if c.Fstype != "" || c.Addr != "" || len(c.Volumes) != 0 || len(c.Fsmap) != 0 {
		panic("unsupported rootfs(temporary)")
	}
	mounts := []*hyperstartgrpc.Mount{{Dest: "/", Source: "vm:/dev/hostfs/" + c.Image + "/" + c.Rootfs}}
	return &hyperstartgrpc.Container{
		Id:     c.Id,
		Mounts: mounts,
		Sysctl: c.Sysctl,
	}
}

func (h *grpcBasedHyperstart) NewContainer(c *hyperstartjson.Container) error {
	_, err := h.grpc.AddContainer(h.ctx, &hyperstartgrpc.AddContainerRequest{
		Container: container4json2grpc(c),
		Init:      process4json2grpc(c.Process),
	})
	return err
}

func (h *grpcBasedHyperstart) RestoreContainer(c *hyperstartjson.Container) error {
	// nothing to do
	return nil
}

func (h *grpcBasedHyperstart) AddProcess(container string, p *hyperstartjson.Process) error {
	_, err := h.grpc.AddProcess(h.ctx, &hyperstartgrpc.AddProcessRequest{
		Container: container,
		Process:   process4json2grpc(p),
	})
	return err
}

func (h *grpcBasedHyperstart) SignalProcess(container, process string, signal syscall.Signal) error {
	_, err := h.grpc.SignalProcess(h.ctx, &hyperstartgrpc.SignalProcessRequest{
		Container: container,
		Process:   process,
		Signal:    uint32(signal),
	})
	return err
}

// wait the process until exit. like waitpid()
// the state is saved until someone calls WaitProcess() if the process exited earlier
// the non-first call of WaitProcess() after process started MAY fail to find the process if the process exited earlier
func (h *grpcBasedHyperstart) WaitProcess(container, process string) int {
	ret, err := h.grpc.WaitProcess(h.ctx, &hyperstartgrpc.WaitProcessRequest{
		Container: container,
		Process:   process,
	})
	if err != nil {
		return -1
	}
	return int(ret.Status)
}

func (h *grpcBasedHyperstart) StartSandbox(pod *hyperstartjson.Pod) error {
	_, err := h.grpc.StartSandbox(h.ctx, &hyperstartgrpc.StartSandboxRequest{
		Hostname: pod.Hostname,
		Dns:      pod.Dns,
	})
	return err
}

func (h *grpcBasedHyperstart) DestroySandbox() error {
	_, err := h.grpc.DestroySandbox(h.ctx, &hyperstartgrpc.DestroySandboxRequest{})
	return err
}
<commit_msg>check if it is io.EOF from grpc.rpcError<commit_after>package libhyperstart

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"syscall"
	"time"

	hyperstartgrpc "github.com/hyperhq/runv/hyperstart/api/grpc"
	hyperstartjson "github.com/hyperhq/runv/hyperstart/api/json"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/grpclog"
)

type grpcBasedHyperstart struct {
	ctx  context.Context
	conn *grpc.ClientConn
	grpc hyperstartgrpc.HyperstartServiceClient
}

// NewGrpcBasedHyperstart create hyperstart interface with grpc protocol
func NewGrpcBasedHyperstart(hyperstartGRPCSock string) (Hyperstart, error) {
	grpclog.SetLogger(log.New(ioutil.Discard, "", log.LstdFlags))
	dialOpts := []grpc.DialOption{grpc.WithInsecure(), grpc.WithTimeout(5 * time.Second)}
	dialOpts = append(dialOpts,
		grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
			return net.DialTimeout("unix", addr, timeout)
		},
		))
	conn, err := grpc.Dial(hyperstartGRPCSock, dialOpts...)
	if err != nil {
		return nil, err
	}
	return &grpcBasedHyperstart{
		ctx:  context.Background(),
		conn: conn,
		grpc: hyperstartgrpc.NewHyperstartServiceClient(conn),
	}, nil
}

func (h *grpcBasedHyperstart) Close() {
	h.conn.Close()
}

func (h *grpcBasedHyperstart) LastStreamSeq() uint64 {
	return 0
}

func (h *grpcBasedHyperstart) APIVersion() (uint32, error) {
	return 4244, nil
}

func (h *grpcBasedHyperstart) PauseSync() error {
	// TODO:
	return nil
}

func (h *grpcBasedHyperstart) Unpause() error {
	// TODO:
	return nil
}

func (h *grpcBasedHyperstart) WriteFile(container, path string, data []byte) error {
	return fmt.Errorf("WriteFile() is unsupported on grpc based hyperstart API")
}

func (h *grpcBasedHyperstart) ReadFile(container, path string) ([]byte, error) {
	return nil, fmt.Errorf("ReadFile() is unsupported on grpc based hyperstart API")
}

func (h *grpcBasedHyperstart) AddRoute(routes []hyperstartjson.Route) error {
	req := &hyperstartgrpc.AddRouteRequest{}
	for _, r := range routes {
		req.Routes = append(req.Routes, &hyperstartgrpc.Route{
			Dest:    r.Dest,
			Gateway: r.Gateway,
			Device:  r.Device,
		})
	}
	_, err := h.grpc.AddRoute(h.ctx, req)
	return err
}

func (h *grpcBasedHyperstart) UpdateInterface(dev, ip, mask string) error {
	_, err := h.grpc.UpdateInterface(h.ctx, &hyperstartgrpc.UpdateInterfaceRequest{
		Device:  dev,
		Address: ip,
		Mask:    mask,
	})
	return err
}

func (h *grpcBasedHyperstart) WriteStdin(container, process string, data []byte) (int, error) {
	ret, err := h.grpc.WriteStdin(h.ctx, &hyperstartgrpc.WriteStreamRequest{
		Container: container,
		Process:   process,
		Data:      data,
	})
	if err == nil {
		return int(ret.Len), nil
	}
	// check if it is &grpc.rpcError{code:0xb, desc:"EOF"} and return io.EOF instead
	if grpc.Code(err) == codes.OutOfRange && grpc.ErrorDesc(err) == "EOF" {
		return 0, io.EOF
	}
	return 0, err
}

func (h *grpcBasedHyperstart) ReadStdout(container, process string, data []byte) (int, error) {
	ret, err := h.grpc.ReadStdout(h.ctx, &hyperstartgrpc.ReadStreamRequest{
		Container: container,
		Process:   process,
		Len:       uint32(len(data)),
	})
	if err == nil {
		copy(data, ret.Data)
		return len(ret.Data), nil
	}
	// check if it is &grpc.rpcError{code:0xb, desc:"EOF"} and return io.EOF instead
	if grpc.Code(err) == codes.OutOfRange && grpc.ErrorDesc(err) == "EOF" {
		return 0, io.EOF
	}
	return 0, err
}

func (h *grpcBasedHyperstart) ReadStderr(container, process string, data []byte) (int, error) {
	ret, err := h.grpc.ReadStderr(h.ctx, &hyperstartgrpc.ReadStreamRequest{
		Container: container,
		Process:   process,
		Len:       uint32(len(data)),
	})
	if err == nil {
		copy(data, ret.Data)
		return len(ret.Data), nil
	}
	// check if it is &grpc.rpcError{code:0xb, desc:"EOF"} and return io.EOF instead
	if grpc.Code(err) == codes.OutOfRange && grpc.ErrorDesc(err) == "EOF" {
		return 0, io.EOF
	}
	return 0, err
}

func (h *grpcBasedHyperstart) CloseStdin(container, process string) error {
	_, err := h.grpc.CloseStdin(h.ctx, &hyperstartgrpc.CloseStdinRequest{
		Container: container,
		Process:   process,
	})
	return err
}

func (h *grpcBasedHyperstart) TtyWinResize(container, process string, row, col uint16) error {
	_, err := h.grpc.TtyWinResize(h.ctx, &hyperstartgrpc.TtyWinResizeRequest{
		Container: container,
		Process:   process,
		Row:       uint32(row),
		Column:    uint32(col),
	})
	return err
}

func (h *grpcBasedHyperstart) OnlineCpuMem() error {
	_, err := h.grpc.OnlineCPUMem(h.ctx, &hyperstartgrpc.OnlineCPUMemRequest{})
	return err
}

func process4json2grpc(p *hyperstartjson.Process) *hyperstartgrpc.Process {
	envs := map[string]string{}
	for _, env := range p.Envs {
		envs[env.Env] = env.Value
	}
	return &hyperstartgrpc.Process{
		Id:       p.Id,
		User:     &hyperstartgrpc.User{Uid: p.User, Gid: p.Group},
		Terminal: p.Terminal,
		Envs:     envs,
		Args:     p.Args,
		Workdir:  p.Workdir,
	}
}

func container4json2grpc(c *hyperstartjson.Container) *hyperstartgrpc.Container {
	if c.Fstype != "" || c.Addr != "" || len(c.Volumes) != 0 || len(c.Fsmap) != 0 {
		panic("unsupported rootfs(temporary)")
	}
	mounts := []*hyperstartgrpc.Mount{{Dest: "/", Source: "vm:/dev/hostfs/" + c.Image + "/" + c.Rootfs}}
	return &hyperstartgrpc.Container{
		Id:     c.Id,
		Mounts: mounts,
		Sysctl: c.Sysctl,
	}
}

func (h *grpcBasedHyperstart) NewContainer(c *hyperstartjson.Container) error {
	_, err := h.grpc.AddContainer(h.ctx, &hyperstartgrpc.AddContainerRequest{
		Container: container4json2grpc(c),
		Init:      process4json2grpc(c.Process),
	})
	return err
}

func (h *grpcBasedHyperstart) RestoreContainer(c *hyperstartjson.Container) error {
	// nothing to do
	return nil
}

func (h *grpcBasedHyperstart) AddProcess(container string, p *hyperstartjson.Process) error {
	_, err := h.grpc.AddProcess(h.ctx, &hyperstartgrpc.AddProcessRequest{
		Container: container,
		Process:   process4json2grpc(p),
	})
	return err
}

func (h *grpcBasedHyperstart) SignalProcess(container, process string, signal syscall.Signal) error {
	_, err := h.grpc.SignalProcess(h.ctx, &hyperstartgrpc.SignalProcessRequest{
		Container: container,
		Process:   process,
		Signal:    uint32(signal),
	})
	return err
}

// wait the process until exit. like waitpid()
// the state is saved until someone calls WaitProcess() if the process exited earlier
// the non-first call of WaitProcess() after process started MAY fail to find the process if the process exited earlier
func (h *grpcBasedHyperstart) WaitProcess(container, process string) int {
	ret, err := h.grpc.WaitProcess(h.ctx, &hyperstartgrpc.WaitProcessRequest{
		Container: container,
		Process:   process,
	})
	if err != nil {
		return -1
	}
	return int(ret.Status)
}

func (h *grpcBasedHyperstart) StartSandbox(pod *hyperstartjson.Pod) error {
	_, err := h.grpc.StartSandbox(h.ctx, &hyperstartgrpc.StartSandboxRequest{
		Hostname: pod.Hostname,
		Dns:      pod.Dns,
	})
	return err
}

func (h *grpcBasedHyperstart) DestroySandbox() error {
	_, err := h.grpc.DestroySandbox(h.ctx, &hyperstartgrpc.DestroySandboxRequest{})
	return err
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes 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 fake

import (
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/pkg/api"
	"k8s.io/client-go/pkg/api/v1"
	core "k8s.io/client-go/testing"
)

func (c *FakeEvents) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
	action := core.NewRootCreateAction(eventsResource, event)
	if c.ns != "" {
		action = core.NewCreateAction(eventsResource, c.ns, event)
	}
	obj, err := c.Fake.Invokes(action, event)
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.Event), err
}

// Update replaces an existing event. Returns the copy of the event the server returns, or an error.
func (c *FakeEvents) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
	action := core.NewRootUpdateAction(eventsResource, event)
	if c.ns != "" {
		action = core.NewUpdateAction(eventsResource, c.ns, event)
	}
	obj, err := c.Fake.Invokes(action, event)
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.Event), err
}

// PatchWithEventNamespace patches an existing event. Returns the copy of the event the server returns, or an error.
func (c *FakeEvents) PatchWithEventNamespace(event *v1.Event, data []byte) (*v1.Event, error) {
	action := core.NewRootPatchAction(eventsResource, event.Name, data)
	if c.ns != "" {
		action = core.NewPatchAction(eventsResource, c.ns, event.Name, data)
	}
	obj, err := c.Fake.Invokes(action, event)
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.Event), err
}

// Search returns a list of events matching the specified object.
func (c *FakeEvents) Search(scheme *runtime.Scheme, objOrRef runtime.Object) (*v1.EventList, error) {
	action := core.NewRootListAction(eventsResource, api.ListOptions{})
	if c.ns != "" {
		action = core.NewListAction(eventsResource, c.ns, api.ListOptions{})
	}
	obj, err := c.Fake.Invokes(action, &v1.EventList{})
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.EventList), err
}

func (c *FakeEvents) GetFieldSelector(involvedObjectName, involvedObjectNamespace, involvedObjectKind, involvedObjectUID *string) fields.Selector {
	action := core.GenericActionImpl{}
	action.Verb = "get-field-selector"
	action.Resource = eventsResource

	c.Fake.Invokes(action, nil)
	return fields.Everything()
}
<commit_msg>fix fake_event_expansion.go<commit_after>/*
Copyright 2014 The Kubernetes 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 fake

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/pkg/api/v1"
	core "k8s.io/client-go/testing"
)

func (c *FakeEvents) CreateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
	action := core.NewRootCreateAction(eventsResource, event)
	if c.ns != "" {
		action = core.NewCreateAction(eventsResource, c.ns, event)
	}
	obj, err := c.Fake.Invokes(action, event)
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.Event), err
}

// Update replaces an existing event. Returns the copy of the event the server returns, or an error.
func (c *FakeEvents) UpdateWithEventNamespace(event *v1.Event) (*v1.Event, error) {
	action := core.NewRootUpdateAction(eventsResource, event)
	if c.ns != "" {
		action = core.NewUpdateAction(eventsResource, c.ns, event)
	}
	obj, err := c.Fake.Invokes(action, event)
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.Event), err
}

// PatchWithEventNamespace patches an existing event. Returns the copy of the event the server returns, or an error.
func (c *FakeEvents) PatchWithEventNamespace(event *v1.Event, data []byte) (*v1.Event, error) {
	action := core.NewRootPatchAction(eventsResource, event.Name, data)
	if c.ns != "" {
		action = core.NewPatchAction(eventsResource, c.ns, event.Name, data)
	}
	obj, err := c.Fake.Invokes(action, event)
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.Event), err
}

// Search returns a list of events matching the specified object.
func (c *FakeEvents) Search(scheme *runtime.Scheme, objOrRef runtime.Object) (*v1.EventList, error) {
	action := core.NewRootListAction(eventsResource, metav1.ListOptions{})
	if c.ns != "" {
		action = core.NewListAction(eventsResource, c.ns, metav1.ListOptions{})
	}
	obj, err := c.Fake.Invokes(action, &v1.EventList{})
	if obj == nil {
		return nil, err
	}

	return obj.(*v1.EventList), err
}

func (c *FakeEvents) GetFieldSelector(involvedObjectName, involvedObjectNamespace, involvedObjectKind, involvedObjectUID *string) fields.Selector {
	action := core.GenericActionImpl{}
	action.Verb = "get-field-selector"
	action.Resource = eventsResource

	c.Fake.Invokes(action, nil)
	return fields.Everything()
}
<|endoftext|>


<commit_before>package model

import "time"

type Iso8601Time struct {
	time.Time
}

const iso8601Layout = "2006-01-02T15:04:05-0700"

func (isoTime *Iso8601Time) UnmarshalJSON(b []byte) (err error) {
	return
}

func (isoTime *Iso8601Time) MarshalJSON() ([]byte, error) {
	return
}

type ApiAiRequest struct {
	ID        string      `json:"id"`
	Timestamp Iso8601Time `json:"timestamp"`
	Result    struct {
		Source           string `json:"source"`
		ResolvedQuery    string `json:"resolvedQuery"`
		Speech           string `json:"speech"`
		Action           string `json:"action"`
		ActionIncomplete bool   `json:"actionIncomplete"`
		Parameters       struct {
		} `json:"parameters"`
		Contexts []interface{} `json:"contexts"`
		Metadata struct {
			IntentID                  string `json:"intentId"`
			WebhookUsed               string `json:"webhookUsed"`
			WebhookForSlotFillingUsed string `json:"webhookForSlotFillingUsed"`
			IntentName                string `json:"intentName"`
		} `json:"metadata"`
		Fulfillment struct {
			Speech   string `json:"speech"`
			Messages []struct {
				Type   int    `json:"type"`
				Speech string `json:"speech"`
			} `json:"messages"`
		} `json:"fulfillment"`
		Score float64 `json:"score"`
	} `json:"result"`
	Status struct {
		Code      int    `json:"code"`
		ErrorType string `json:"errorType"`
	} `json:"status"`
	SessionID       string `json:"sessionId"`
	OriginalRequest struct {
		Source string `json:"source"`
		Data   struct {
			Inputs []struct {
				Arguments []struct {
					RawText   string `json:"raw_text"`
					TextValue string `json:"text_value"`
					Name      string `json:"name"`
				} `json:"arguments"`
				Intent    string `json:"intent"`
				RawInputs []struct {
					Query     string `json:"query"`
					InputType int    `json:"input_type"`
				} `json:"raw_inputs"`
			} `json:"inputs"`
			User struct {
				UserID string `json:"user_id"`
			} `json:"user"`
			Conversation struct {
				ConversationToken string `json:"conversation_token"`
				ConversationID    string `json:"conversation_id"`
				Type              int    `json:"type"`
			} `json:"conversation"`
		} `json:"data"`
	} `json:"originalRequest"`
}
<commit_msg>Enhance parameters field<commit_after>package model

import "time"

type Iso8601Time struct {
	time.Time
}

const iso8601Layout = "2006-01-02T15:04:05-0700"

func (isoTime *Iso8601Time) UnmarshalJSON(b []byte) (err error) {
	return
}

func (isoTime *Iso8601Time) MarshalJSON() ([]byte, error) {
	return nil, nil
}

type ApiAiRequest struct {
	Id        string      `json:"id"`
	Timestamp Iso8601Time `json:"timestamp"`
	Result    struct {
		Source           string `json:"source"`
		ResolvedQuery    string `json:"resolvedQuery"`
		Speech           string `json:"speech"`
		Action           string `json:"action"`
		ActionIncomplete bool   `json:"actionIncomplete"`
		Parameters       struct {
			Parameters map[string]string
		} `json:"parameters"`
		Contexts []interface{} `json:"contexts"`
		Metadata struct {
			IntentID                  string `json:"intentId"`
			WebhookUsed               string `json:"webhookUsed"`
			WebhookForSlotFillingUsed string `json:"webhookForSlotFillingUsed"`
			IntentName                string `json:"intentName"`
		} `json:"metadata"`
		Fulfillment struct {
			Speech   string `json:"speech"`
			Messages []struct {
				Type   int    `json:"type"`
				Speech string `json:"speech"`
			} `json:"messages"`
		} `json:"fulfillment"`
		Score float64 `json:"score"`
	} `json:"result"`
	Status struct {
		Code      int    `json:"code"`
		ErrorType string `json:"errorType"`
	} `json:"status"`
	SessionID       string `json:"sessionId"`
	OriginalRequest struct {
		Source string `json:"source"`
		Data   struct {
			Inputs []struct {
				Arguments []struct {
					RawText   string `json:"raw_text"`
					TextValue string `json:"text_value"`
					Name      string `json:"name"`
				} `json:"arguments"`
				Intent    string `json:"intent"`
				RawInputs []struct {
					Query     string `json:"query"`
					InputType int    `json:"input_type"`
				} `json:"raw_inputs"`
			} `json:"inputs"`
			User struct {
				UserID string `json:"user_id"`
			} `json:"user"`
			Conversation struct {
				ConversationToken string `json:"conversation_token"`
				ConversationID    string `json:"conversation_id"`
				Type              int    `json:"type"`
			} `json:"conversation"`
		} `json:"data"`
	} `json:"originalRequest"`
}
<|endoftext|>


<commit_before>package main

import (
	"./goleg"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)

type Config struct {
	// Base settings (required)
	Listen  string `json:"listen"`
	DataDir string `json: "datadir"`
	// HTTPS settings
	UseHTTPS         bool   `json:"usehttps"`
	CertFile         string `json:"certfile"`
	PkeyFile         string `json:"pkeyfile"`
	SplayTreeEnabled bool   `json:"splaytreeenabled"`
	LZ4Enabled       bool   `json:"lz4enabled"`
	AOLEnabled       bool   `json:"aolenabled"`
}

var config Config
var databases map[string]goleg.Database

const (
	Usage = `
Usage: %s -config <config path> [options]
	Config path:
		Path to a configuration file. This is required.
Options:
	-v
		Version
	-h
		This help.
	-bind
		Override Listen directive in configuration.
	-dir
		Override db storage location in configuration.
	-enable-lz4
		Enables LZ4 compression.
	-enable-splay-tree
		Enables the splay tree.
	-enable-aol
		Enables the append-only log.
`
)

func main() {
	// Parse command line flags (if there are)
	directory := flag.String("dir", "", "Directory where to store dumps and data")
	configfile := flag.String("config", "", "Config file to read settings from")
	bindaddr := flag.String("bind", "", "Address and port to bind, host:port")
	splaytreeenabled := flag.Bool("enable-splay-tree", false, "Enables the splay tree")
	lz4enabled := flag.Bool("enable-lz4", false, "Enables LZ4 compression")
	aolenabled := flag.Bool("enable-aol", false, "Enables the append-only log")

	flag.Parse()

	if *configfile == "" {
		fmt.Println("Config file is required")
		fmt.Printf(Usage, os.Args[0])
		os.Exit(1)
	}

	// Parse config file
	rawconf, err := ioutil.ReadFile(*configfile)
	if err != nil {
		fmt.Println("Could not read configuration. Please see the documentation.")
		fmt.Printf(Usage, os.Args[0])
		os.Exit(1)
	}
	err = json.Unmarshal(rawconf, &config)
	if err != nil {
		panic(err.Error())
	}

	databases = make(map[string]goleg.Database)

	// Override config option with command line ones
	if *directory != "" {
		config.DataDir = *directory
	}

	if *bindaddr != "" {
		config.Listen = *bindaddr
	}

	if *splaytreeenabled {
		config.SplayTreeEnabled = *splaytreeenabled
	}

	if *lz4enabled {
		config.LZ4Enabled = *lz4enabled
	}

	if *aolenabled {
		config.AOLEnabled = *aolenabled
	}

	http.HandleFunc("/", handler)
	defer unload()
	var httperr error
	log.Println("Starting server...")
	if config.LZ4Enabled {
		log.Println("LZ4 compression is enabled")
	}
	if config.AOLEnabled {
		log.Println("Append-only log is enabled")
	}
	if config.SplayTreeEnabled {
		log.Println("Splay-tree is enabled")
	}
	if config.UseHTTPS {
		log.Println("Listening on https://" + config.Listen)
		httperr = http.ListenAndServeTLS(config.Listen, config.CertFile, config.PkeyFile, nil)
	} else {
		log.Println("Listening on http://" + config.Listen)
		httperr = http.ListenAndServe(config.Listen, nil)
	}
	if httperr != nil {
		log.Fatal(httperr)
	}
}

func unload() {
	for v := range databases {
		databases[v].Close()
	}
}
<commit_msg>Handle CTRL+C properly.<commit_after>package main

import (
	"./goleg"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
)

type Config struct {
	// Base settings (required)
	Listen  string `json:"listen"`
	DataDir string `json: "datadir"`
	// HTTPS settings
	UseHTTPS         bool   `json:"usehttps"`
	CertFile         string `json:"certfile"`
	PkeyFile         string `json:"pkeyfile"`
	SplayTreeEnabled bool   `json:"splaytreeenabled"`
	LZ4Enabled       bool   `json:"lz4enabled"`
	AOLEnabled       bool   `json:"aolenabled"`
}

var config Config
var databases map[string]goleg.Database

const (
	Usage = `
Usage: %s -config <config path> [options]
	Config path:
		Path to a configuration file. This is required.
Options:
	-v
		Version
	-h
		This help.
	-bind
		Override Listen directive in configuration.
	-dir
		Override db storage location in configuration.
	-enable-lz4
		Enables LZ4 compression.
	-enable-splay-tree
		Enables the splay tree.
	-enable-aol
		Enables the append-only log.
`
)

func main() {
	// Parse command line flags (if there are)
	directory := flag.String("dir", "", "Directory where to store dumps and data")
	configfile := flag.String("config", "", "Config file to read settings from")
	bindaddr := flag.String("bind", "", "Address and port to bind, host:port")
	splaytreeenabled := flag.Bool("enable-splay-tree", false, "Enables the splay tree")
	lz4enabled := flag.Bool("enable-lz4", false, "Enables LZ4 compression")
	aolenabled := flag.Bool("enable-aol", false, "Enables the append-only log")

	signals := make(chan os.Signal, 1)
	signal.Notify(signals, os.Interrupt)
	go func() {
		<- signals
		unload()
		os.Exit(0)
	}()

	flag.Parse()

	if *configfile == "" {
		fmt.Println("Config file is required")
		fmt.Printf(Usage, os.Args[0])
		os.Exit(1)
	}

	// Parse config file
	rawconf, err := ioutil.ReadFile(*configfile)
	if err != nil {
		fmt.Println("Could not read configuration. Please see the documentation.")
		fmt.Printf(Usage, os.Args[0])
		os.Exit(1)
	}
	err = json.Unmarshal(rawconf, &config)
	if err != nil {
		panic(err.Error())
	}

	databases = make(map[string]goleg.Database)

	// Override config option with command line ones
	if *directory != "" {
		config.DataDir = *directory
	}

	if *bindaddr != "" {
		config.Listen = *bindaddr
	}

	if *splaytreeenabled {
		config.SplayTreeEnabled = *splaytreeenabled
	}

	if *lz4enabled {
		config.LZ4Enabled = *lz4enabled
	}

	if *aolenabled {
		config.AOLEnabled = *aolenabled
	}

	http.HandleFunc("/", handler)
	defer unload()
	var httperr error
	log.Println("Starting server...")
	if config.LZ4Enabled {
		log.Println("LZ4 compression is enabled")
	}
	if config.AOLEnabled {
		log.Println("Append-only log is enabled")
	}
	if config.SplayTreeEnabled {
		log.Println("Splay-tree is enabled")
	}
	if config.UseHTTPS {
		log.Println("Listening on https://" + config.Listen)
		httperr = http.ListenAndServeTLS(config.Listen, config.CertFile, config.PkeyFile, nil)
	} else {
		log.Println("Listening on http://" + config.Listen)
		httperr = http.ListenAndServe(config.Listen, nil)
	}
	if httperr != nil {
		log.Fatal(httperr)
	}
}

func unload() {
	for v := range databases {
		log.Println("Closing " + v + "...")
		databases[v].Close()
		log.Println(v + " closed.")
	}
}
<|endoftext|>


<commit_before>// Package counters provides a simple counter, max and min functionalities.
// All counters are kept in CounterBox.
// Library is thread safe.
package counters

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"sort"
	"strings"
	"sync"
	"sync/atomic"
	"text/template"
)

// MaxMinValue is an interface for minima and maxima counters.
type MaxMinValue interface {
	// Set allows to update value if necessary.
	Set(int)
	// Name returns a name of counter.
	Name() string
	// Value returns a current value.
	Value() int64
}

// Counter is an interface for integer increase only counter.
type Counter interface {
	// Increment increases counter by one.
	Increment()
	// IncrementBy increases counter by given number.
	IncrementBy(num int)
	// Name returns a name of counter.
	Name() string
	// Value returns a current value of counter.
	Value() int64
}

// CounterBox is a main type, it keeps references to all counters
// requested from it.
type CounterBox struct {
	counters map[string]*counterImpl
	min      map[string]*minImpl
	max      map[string]*maxImpl
	m        *sync.RWMutex
}

// NewCounterBox creates a new object to keep all counters.
func NewCounterBox() *CounterBox {
	return &CounterBox{
		counters: make(map[string]*counterImpl),
		min:      make(map[string]*minImpl),
		max:      make(map[string]*maxImpl),
		m:        &sync.RWMutex{},
	}
}

// CreateHttpHandler creates a simple handler printing values of all counters.
func (c *CounterBox) CreateHttpHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		c.m.RLock()
		fmt.Fprintf(w, "Counters %d\n", len(c.counters))
		for k, v := range c.counters {
			fmt.Fprintf(w, "%s=%d\n", k, v.Value())
		}
		fmt.Fprintf(w, "\nMax values %d\n", len(c.max))
		for k, v := range c.max {
			fmt.Fprintf(w, "%s=%d\n", k, v.Value())
		}
		fmt.Fprintf(w, "\nMin values %d\n", len(c.min))
		for k, v := range c.min {
			fmt.Fprintf(w, "%s=%d\n", k, v.Value())
		}
		c.m.RUnlock()
	}
}

// GetCounter returns a counter of given name, if doesn't exist than create.
func (c *CounterBox) GetCounter(name string) Counter {
	c.m.RLock()
	v, ok := c.counters[name]
	c.m.RUnlock()
	if !ok {
		c.m.Lock()
		if v, ok = c.counters[name]; !ok {
			v = &counterImpl{name, 0}
			c.counters[name] = v
		}
		c.m.Unlock()
	}
	return v
}

// GetMin returns a minima counter of given name, if doesn't exist than create.
func (c *CounterBox) GetMin(name string) MaxMinValue {
	c.m.RLock()
	v, ok := c.min[name]
	c.m.RUnlock()
	if !ok {
		c.m.Lock()
		if v, ok = c.min[name]; !ok {
			v = &minImpl{name, 0}
			c.min[name] = v
		}
		c.m.Unlock()
	}
	return v
}

// GetMax returns a maxima counter of given name, if doesn't exist than create.
func (c *CounterBox) GetMax(name string) MaxMinValue {
	c.m.RLock()
	v, ok := c.max[name]
	c.m.RUnlock()
	if !ok {
		c.m.Lock()
		if v, ok = c.max[name]; !ok {
			v = &maxImpl{name, 0}
			c.max[name] = v
		}
		c.m.Unlock()
	}
	return v
}

var tmpl = template.Must(template.New("main").Parse(`== Counters ==
{{- range .Counters}}
  {{.Name}}: {{.Value}}
{{- end}}
== Min values ==
{{- range .Min}}
  {{.Name}}: {{.Value}}
{{- end}}
== Max values ==
{{- range .Max}}
  {{.Name}}: {{.Value}}
{{- end -}}
`))

func (c *CounterBox) WriteTo(w io.Writer) {
	c.m.RLock()
	data := &struct {
		Counters []Counter
		Min      []MaxMinValue
		Max      []MaxMinValue
	}{}
	for _, c := range c.counters {
		data.Counters = append(data.Counters, c)
	}
	for _, c := range c.min {
		data.Min = append(data.Min, c)
	}
	for _, c := range c.max {
		data.Max = append(data.Max, c)
	}
	sort.Slice(data.Counters, func(i, j int) bool { return strings.Compare(data.Counters[i].Name(), data.Counters[j].Name()) < 0 })
	sort.Slice(data.Min, func(i, j int) bool { return strings.Compare(data.Min[i].Name(), data.Min[j].Name()) < 0 })
	sort.Slice(data.Max, func(i, j int) bool { return strings.Compare(data.Max[i].Name(), data.Max[j].Name()) < 0 })
	tmpl.Execute(w, data)
	c.m.RUnlock()
}

func (c *CounterBox) String() string {
	buf := &bytes.Buffer{}
	c.WriteTo(buf)
	return buf.String()
}

type counterImpl struct {
	name  string
	value int64
}

func (c *counterImpl) Increment() {
	atomic.AddInt64(&c.value, 1)
}

func (c *counterImpl) IncrementBy(num int) {
	atomic.AddInt64(&c.value, int64(num))
}

func (c *counterImpl) Name() string {
	return c.name
}

func (c *counterImpl) Value() int64 {
	return atomic.LoadInt64(&c.value)
}

type maxImpl counterImpl

func (m *maxImpl) Set(v int) {
	done := false
	v64 := int64(v)
	for !done {
		if o := atomic.LoadInt64(&m.value); v64 > o {
			done = atomic.CompareAndSwapInt64(&m.value, o, v64)
		} else {
			done = true
		}
	}
}

func (m *maxImpl) Name() string {
	return m.name
}

func (m *maxImpl) Value() int64 {
	return atomic.LoadInt64(&m.value)
}

type minImpl counterImpl

func (m *minImpl) Set(v int) {
	done := false
	v64 := int64(v)
	for !done {
		if o := atomic.LoadInt64(&m.value); v64 < o {
			done = atomic.CompareAndSwapInt64(&m.value, o, v64)
		} else {
			done = true
		}
	}
}

func (m *minImpl) Name() string {
	return m.name
}

func (m *minImpl) Value() int64 {
	return atomic.LoadInt64(&m.value)
}
<commit_msg>fix min impl<commit_after>// Package counters provides a simple counter, max and min functionalities.
// All counters are kept in CounterBox.
// Library is thread safe.
package counters

import (
	"bytes"
	"fmt"
	"io"
	"math"
	"net/http"
	"sort"
	"strings"
	"sync"
	"sync/atomic"
	"text/template"
)

// MaxMinValue is an interface for minima and maxima counters.
type MaxMinValue interface {
	// Set allows to update value if necessary.
	Set(int)
	// Name returns a name of counter.
	Name() string
	// Value returns a current value.
	Value() int64
}

// Counter is an interface for integer increase only counter.
type Counter interface {
	// Increment increases counter by one.
	Increment()
	// IncrementBy increases counter by given number.
	IncrementBy(num int)
	// Name returns a name of counter.
	Name() string
	// Value returns a current value of counter.
	Value() int64
}

// CounterBox is a main type, it keeps references to all counters
// requested from it.
type CounterBox struct {
	counters map[string]*counterImpl
	min      map[string]*minImpl
	max      map[string]*maxImpl
	m        *sync.RWMutex
}

// NewCounterBox creates a new object to keep all counters.
func NewCounterBox() *CounterBox {
	return &CounterBox{
		counters: make(map[string]*counterImpl),
		min:      make(map[string]*minImpl),
		max:      make(map[string]*maxImpl),
		m:        &sync.RWMutex{},
	}
}

// CreateHttpHandler creates a simple handler printing values of all counters.
func (c *CounterBox) CreateHttpHandler() http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		c.m.RLock()
		fmt.Fprintf(w, "Counters %d\n", len(c.counters))
		for k, v := range c.counters {
			fmt.Fprintf(w, "%s=%d\n", k, v.Value())
		}
		fmt.Fprintf(w, "\nMax values %d\n", len(c.max))
		for k, v := range c.max {
			fmt.Fprintf(w, "%s=%d\n", k, v.Value())
		}
		fmt.Fprintf(w, "\nMin values %d\n", len(c.min))
		for k, v := range c.min {
			fmt.Fprintf(w, "%s=%d\n", k, v.Value())
		}
		c.m.RUnlock()
	}
}

// GetCounter returns a counter of given name, if doesn't exist than create.
func (c *CounterBox) GetCounter(name string) Counter {
	c.m.RLock()
	v, ok := c.counters[name]
	c.m.RUnlock()
	if !ok {
		c.m.Lock()
		if v, ok = c.counters[name]; !ok {
			v = &counterImpl{name, 0}
			c.counters[name] = v
		}
		c.m.Unlock()
	}
	return v
}

// GetMin returns a minima counter of given name, if doesn't exist than create.
func (c *CounterBox) GetMin(name string) MaxMinValue {
	c.m.RLock()
	v, ok := c.min[name]
	c.m.RUnlock()
	if !ok {
		c.m.Lock()
		if v, ok = c.min[name]; !ok {
			v = &minImpl{name, math.MaxInt64}
			c.min[name] = v
		}
		c.m.Unlock()
	}
	return v
}

// GetMax returns a maxima counter of given name, if doesn't exist than create.
func (c *CounterBox) GetMax(name string) MaxMinValue {
	c.m.RLock()
	v, ok := c.max[name]
	c.m.RUnlock()
	if !ok {
		c.m.Lock()
		if v, ok = c.max[name]; !ok {
			v = &maxImpl{name, 0}
			c.max[name] = v
		}
		c.m.Unlock()
	}
	return v
}

var tmpl = template.Must(template.New("main").Parse(`== Counters ==
{{- range .Counters}}
  {{.Name}}: {{.Value}}
{{- end}}
== Min values ==
{{- range .Min}}
  {{.Name}}: {{.Value}}
{{- end}}
== Max values ==
{{- range .Max}}
  {{.Name}}: {{.Value}}
{{- end -}}
`))

func (c *CounterBox) WriteTo(w io.Writer) {
	c.m.RLock()
	data := &struct {
		Counters []Counter
		Min      []MaxMinValue
		Max      []MaxMinValue
	}{}
	for _, c := range c.counters {
		data.Counters = append(data.Counters, c)
	}
	for _, c := range c.min {
		data.Min = append(data.Min, c)
	}
	for _, c := range c.max {
		data.Max = append(data.Max, c)
	}
	sort.Slice(data.Counters, func(i, j int) bool { return strings.Compare(data.Counters[i].Name(), data.Counters[j].Name()) < 0 })
	sort.Slice(data.Min, func(i, j int) bool { return strings.Compare(data.Min[i].Name(), data.Min[j].Name()) < 0 })
	sort.Slice(data.Max, func(i, j int) bool { return strings.Compare(data.Max[i].Name(), data.Max[j].Name()) < 0 })
	tmpl.Execute(w, data)
	c.m.RUnlock()
}

func (c *CounterBox) String() string {
	buf := &bytes.Buffer{}
	c.WriteTo(buf)
	return buf.String()
}

type counterImpl struct {
	name  string
	value int64
}

func (c *counterImpl) Increment() {
	atomic.AddInt64(&c.value, 1)
}

func (c *counterImpl) IncrementBy(num int) {
	atomic.AddInt64(&c.value, int64(num))
}

func (c *counterImpl) Name() string {
	return c.name
}

func (c *counterImpl) Value() int64 {
	return atomic.LoadInt64(&c.value)
}

type maxImpl counterImpl

func (m *maxImpl) Set(v int) {
	done := false
	v64 := int64(v)
	for !done {
		if o := atomic.LoadInt64(&m.value); v64 > o {
			done = atomic.CompareAndSwapInt64(&m.value, o, v64)
		} else {
			done = true
		}
	}
}

func (m *maxImpl) Name() string {
	return m.name
}

func (m *maxImpl) Value() int64 {
	return atomic.LoadInt64(&m.value)
}

type minImpl counterImpl

func (m *minImpl) Set(v int) {
	done := false
	v64 := int64(v)
	for !done {
		if o := atomic.LoadInt64(&m.value); v64 < o {
			done = atomic.CompareAndSwapInt64(&m.value, o, v64)
		} else {
			done = true
		}
	}
}

func (m *minImpl) Name() string {
	return m.name
}

func (m *minImpl) Value() int64 {
	return atomic.LoadInt64(&m.value)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"sync"
)

var usage = `Usage: cp source target
       cp file ... directory`

func main() {
	elog := log.New(os.Stderr, "cp: ", 0)
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, usage)
		flag.PrintDefaults()
	}
	flag.Parse()
	args := flag.Args()
	if len(args) < 2 {
		flag.Usage()
		os.Exit(1)
	}
	if len(args) == 2 {
		from, to := args[0], args[1]
		stat, err := os.Stat(to)
		if err != nil && !os.IsNotExist(err) {
			elog.Fatal(err)
		}
		if stat != nil && stat.IsDir() {
			to = to + "/" + path.Base(from)
		}
		if err := cp(from, to); err != nil {
			elog.Fatal(err)
		}
	} else {
		dir := args[len(args)-1]
		stat, err := os.Stat(dir)
		if err != nil {
			elog.Fatal(err)
		}
		if !stat.IsDir() {
			elog.Fatal("multi-file target must be directory\n" + usage)
		}
		var wg sync.WaitGroup
		for _, fname := range args[:len(args)-1] {
			wg.Add(1)
			// copy files concurrently
			go func(fname string) {
				defer wg.Done()
				err := cp(fname, dir+"/"+path.Base(fname))
				if err != nil {
					elog.Print(err)
				}
			}(fname)
		}
		wg.Wait()
	}
}

func cp(from, to string) error {
	stat, err := os.Stat(from)
	if err != nil {
		return err
	}
	if stat.IsDir() {
		return errors.New(from + " is a directory (not copied)")
	}
	source, err := os.Open(from)
	if err != nil {
		return err
	}
	defer source.Close()
	dest, err := os.Create(to)
	if err != nil {
		return err
	}
	defer dest.Close()
	r, w := bufio.NewReader(source), bufio.NewWriter(dest)
	defer w.Flush()
	_, err = io.Copy(w, r)
	return err
}
<commit_msg>cp: set destination mode to source mode<commit_after>package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"sync"
)

var usage = `Usage: cp source target
       cp file ... directory`

func main() {
	elog := log.New(os.Stderr, "cp: ", 0)
	flag.Usage = func() {
		fmt.Fprintln(os.Stderr, usage)
		flag.PrintDefaults()
	}
	flag.Parse()
	args := flag.Args()
	if len(args) < 2 {
		flag.Usage()
		os.Exit(1)
	}
	if len(args) == 2 {
		from, to := args[0], args[1]
		stat, err := os.Stat(to)
		if err != nil && !os.IsNotExist(err) {
			elog.Fatal(err)
		}
		if stat != nil && stat.IsDir() {
			to = to + "/" + path.Base(from)
		}
		if err := cp(from, to); err != nil {
			elog.Fatal(err)
		}
	} else {
		dir := args[len(args)-1]
		stat, err := os.Stat(dir)
		if err != nil {
			elog.Fatal(err)
		}
		if !stat.IsDir() {
			elog.Fatal("multi-file target must be directory\n" + usage)
		}
		var wg sync.WaitGroup
		for _, fname := range args[:len(args)-1] {
			wg.Add(1)
			// copy files concurrently
			go func(fname string) {
				defer wg.Done()
				err := cp(fname, dir+"/"+path.Base(fname))
				if err != nil {
					elog.Print(err)
				}
			}(fname)
		}
		wg.Wait()
	}
}

func cp(from, to string) error {
	stat, err := os.Stat(from)
	if err != nil {
		return err
	}
	if stat.IsDir() {
		return errors.New(from + " is a directory (not copied)")
	}
	source, err := os.Open(from)
	if err != nil {
		return err
	}
	defer source.Close()
	dest, err := os.OpenFile(to, os.O_RDWR|os.O_CREATE|os.O_TRUNC, stat.Mode())
	if err != nil {
		return err
	}
	defer dest.Close()
	r, w := bufio.NewReader(source), bufio.NewWriter(dest)
	defer w.Flush()
	_, err = io.Copy(w, r)
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)

var files = map[string]string{
	"ChromeStandaloneSetup.exe": "https://dl.google.com/tag/s/appguid%3D%7B8A69D345-D564-463C-AFF1-A69D9E530F96%7D%26iid%3D%7BC159FD9F-6827-8E7E-0CC8-7783A1335AA5%7D%26lang%3Den%26browser%3D4%26usagestats%3D0%26appname%3DGoogle%2520Chrome%26needsadmin%3Dprefers%26installdataindex%3Ddefaultbrowser/update2/installers/ChromeStandaloneSetup.exe",
	"Mercurial.exe":             "http://mercurial.selenic.com/release/windows/Mercurial-3.1-x64.exe",
	"tdm64-gcc-4.8.1-3.exe":     "http://downloads.sourceforge.net/project/tdm-gcc/TDM-GCC%20Installer/tdm64-gcc-4.8.1-3.exe?r=http%3A%2F%2Ftdm-gcc.tdragon.net%2Fdownload&ts=1407729829&use_mirror=ufpr",
	wixFilename:                 "http://download-codeplex.sec.s-msft.com/Download/Release?ProjectName=wix&DownloadId=204417&FileTime=129409234222130000&Build=20919",
}

const wixFilename = "Wix35.msi"

var altMain func()

var (
	flagYes = flag.Bool("yes", false, "Run without prompt")
	release = flag.Bool("release", false, "Set up a release builder")
)

func main() {
	if runtime.GOOS != "windows" {
		altMain()
		return
	}
	flag.Parse()
	if !*flagYes {
		log.Printf("This program will install Go, Mingw, Mercurial, Chrome, etc. Type 'go<enter>' to proceed.")
		if !awaitString("go") {
			log.Printf("Canceled.")
			awaitEnter()
			return
		}
	}

	log.Printf("Downloading files.")
	var wg sync.WaitGroup
	for file, url := range files {
		if !*release && file == wixFilename {
			continue
		}
		wg.Add(1)
		go download(file, url, &wg)
	}
	wg.Wait()

	checkHg()
	checkGcc()

	checkoutGo()

	runGoMakeBat("386")
	runGoMakeBat("amd64")

	if *release {
		buildMakerelease()
	}

	log.Printf(`Installed go to %v, please add %v\bin to your PATH`, goroot(), goroot())

	fmt.Println("[ Press enter to exit ]")
	awaitEnter()
}

const gccPath = `C:\TDM-GCC-64\bin`

func runGoMakeBat(arch string) {
	if arch != "386" && arch != "amd64" {
		panic("invalid arch " + arch)
	}

	testFile := filepath.Join(goroot(), "pkg", "tool", "windows_"+arch, "api.exe")
	if fileExists(testFile) {
		log.Printf("Skipping make.bat for windows_%s; already built.", arch)
		return
	}

	log.Printf("Running make.bat for arch %s ...", arch)
	cmd := exec.Command(filepath.Join(goroot(), "src", "make.bat"))
	cmd.Dir = filepath.Join(goroot(), "src")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	cmd.Env = append([]string{
		"GOARCH=" + arch,
		"PATH=" + gccPath + ";" + os.Getenv("PATH"),
	}, removeEnvs(os.Environ(), "PATH")...)

	err := cmd.Run()
	if err != nil {
		log.Fatalf("make.bat for arch %s: %v", arch, err)
	}
	log.Printf("ran make.bat for arch %s", arch)
}

func buildMakerelease() {
	goCmd := filepath.Join(goroot(), "bin", "go.exe")
	mrDir := filepath.Join(goroot(), "misc", "makerelease")
	env := append(
		[]string{"GOPATH=" + gopath()},
		removeEnvs(os.Environ(), "GOPATH")...)
	bin := filepath.Join(home(), "makerelease.exe")

	goDo := func(args ...string) {
		cmd := exec.Command(goCmd, args...)
		cmd.Dir = mrDir
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Env = env
		if err := cmd.Run(); err != nil {
			log.Fatal(err)
		}
	}

	log.Print("Fetching dependencies for makerelease...")
	goDo("get", "-d")
	log.Println("Building and installing makerelease to", bin)
	goDo("build", "-o", bin)
}

func removeEnvs(envs []string, removeKeys ...string) []string {
	var ret []string
	for _, env := range envs {
		include := true
		for _, remove := range removeKeys {
			if strings.HasPrefix(env, remove+"=") {
				include = false
				break
			}
		}
		if include {
			ret = append(ret, env)
		}
	}
	return ret
}

func checkHg() {
	for {
		if _, ok := hgBin(); ok {
			break
		}
		log.Print("Can't find hg binary. Install Mercurial and then press enter...")
		awaitEnter()
	}
}

const hgDefaultPath = `C:\Program Files\Mercurial\hg.exe`

func hgBin() (string, bool) {
	b, err := exec.LookPath("hg")
	if err != nil {
		b = hgDefaultPath
	}
	return b, fileExists(b)
}

func checkGcc() {
	for !fileExists(gccPath) {
		log.Printf("%s doesn't exist. Install gcc and then press enter...", gccPath)
		awaitEnter()
	}
}

func checkoutGo() {
	if fileExists(goroot()) {
		log.Printf("GOROOT %s already exists; skipping hg checkout", goroot())
		return
	}
	log.Printf("Checking out Go source using Mercurial (hg)")

	hg, _ := hgBin()
	cmd := exec.Command(hg, "clone", "https://code.google.com/p/go", "goroot")
	cmd.Dir = home()
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("hg clone failed. Is Mercurial installed? Re-run later. Error: %v", err)
	}
	log.Printf("Checked out Go.")
}

func awaitEnter() {
	var buf [1]byte
	os.Stdin.Read(buf[:])
}

func awaitString(want string) bool {
	br := bufio.NewReader(os.Stdin)
	ln, _, _ := br.ReadLine()
	return strings.TrimSpace(string(ln)) == want
}

func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func home() string { return os.Getenv("HOMEPATH") }

func goroot() string { return filepath.Join(home(), "goroot") }

func gopath() string { return filepath.Join(home(), "gopath") }

func download(file, url string, wg *sync.WaitGroup) {
	defer wg.Done()

	dst := filepath.Join(home(), "Desktop", file)
	if _, err := os.Stat(dst); err == nil {
		log.Printf("%s already on desktop; skipping", file)
		return
	}

	res, err := http.Get(url)
	if err != nil {
		log.Fatalf("Error fetching %v: %v", url, err)
	}
	tmp := dst + ".tmp"
	os.Remove(tmp)
	os.Remove(dst)
	f, err := os.Create(tmp)
	if err != nil {
		log.Fatal(err)
	}
	n, err := io.Copy(f, res.Body)
	res.Body.Close()
	if err != nil {
		log.Fatalf("Error reading %v: %v", url, err)
	}
	f.Close()
	err = os.Rename(tmp, dst)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Downladed %s (%d bytes) to desktop", file, n)
}
<commit_msg>Remove Chrome. No longer useful once we found bitsadmin /transfer<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)

var files = map[string]string{
	"Mercurial.exe":         "http://mercurial.selenic.com/release/windows/Mercurial-3.1-x64.exe",
	"tdm64-gcc-4.8.1-3.exe": "http://downloads.sourceforge.net/project/tdm-gcc/TDM-GCC%20Installer/tdm64-gcc-4.8.1-3.exe?r=http%3A%2F%2Ftdm-gcc.tdragon.net%2Fdownload&ts=1407729829&use_mirror=ufpr",
	wixFilename:             "http://download-codeplex.sec.s-msft.com/Download/Release?ProjectName=wix&DownloadId=204417&FileTime=129409234222130000&Build=20919",
}

const wixFilename = "Wix35.msi"

var altMain func()

var (
	flagYes = flag.Bool("yes", false, "Run without prompt")
	release = flag.Bool("release", false, "Set up a release builder")
)

func main() {
	if runtime.GOOS != "windows" {
		altMain()
		return
	}
	flag.Parse()
	if !*flagYes {
		log.Printf("This program will install Go, Mingw, Mercurial, etc. Type 'go<enter>' to proceed.")
		if !awaitString("go") {
			log.Printf("Canceled.")
			awaitEnter()
			return
		}
	}

	log.Printf("Downloading files.")
	var wg sync.WaitGroup
	for file, url := range files {
		if !*release && file == wixFilename {
			continue
		}
		wg.Add(1)
		go download(file, url, &wg)
	}
	wg.Wait()

	checkHg()
	checkGcc()

	checkoutGo()

	runGoMakeBat("386")
	runGoMakeBat("amd64")

	if *release {
		buildMakerelease()
	}

	log.Printf(`Installed go to %v, please add %v\bin to your PATH`, goroot(), goroot())

	fmt.Println("[ Press enter to exit ]")
	awaitEnter()
}

const gccPath = `C:\TDM-GCC-64\bin`

func runGoMakeBat(arch string) {
	if arch != "386" && arch != "amd64" {
		panic("invalid arch " + arch)
	}

	testFile := filepath.Join(goroot(), "pkg", "tool", "windows_"+arch, "api.exe")
	if fileExists(testFile) {
		log.Printf("Skipping make.bat for windows_%s; already built.", arch)
		return
	}

	log.Printf("Running make.bat for arch %s ...", arch)
	cmd := exec.Command(filepath.Join(goroot(), "src", "make.bat"))
	cmd.Dir = filepath.Join(goroot(), "src")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	cmd.Env = append([]string{
		"GOARCH=" + arch,
		"PATH=" + gccPath + ";" + os.Getenv("PATH"),
	}, removeEnvs(os.Environ(), "PATH")...)

	err := cmd.Run()
	if err != nil {
		log.Fatalf("make.bat for arch %s: %v", arch, err)
	}
	log.Printf("ran make.bat for arch %s", arch)
}

func buildMakerelease() {
	goCmd := filepath.Join(goroot(), "bin", "go.exe")
	mrDir := filepath.Join(goroot(), "misc", "makerelease")
	env := append(
		[]string{"GOPATH=" + gopath()},
		removeEnvs(os.Environ(), "GOPATH")...)
	bin := filepath.Join(home(), "makerelease.exe")

	goDo := func(args ...string) {
		cmd := exec.Command(goCmd, args...)
		cmd.Dir = mrDir
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Env = env
		if err := cmd.Run(); err != nil {
			log.Fatal(err)
		}
	}

	log.Print("Fetching dependencies for makerelease...")
	goDo("get", "-d")
	log.Println("Building and installing makerelease to", bin)
	goDo("build", "-o", bin)
}

func removeEnvs(envs []string, removeKeys ...string) []string {
	var ret []string
	for _, env := range envs {
		include := true
		for _, remove := range removeKeys {
			if strings.HasPrefix(env, remove+"=") {
				include = false
				break
			}
		}
		if include {
			ret = append(ret, env)
		}
	}
	return ret
}

func checkHg() {
	for {
		if _, ok := hgBin(); ok {
			break
		}
		log.Print("Can't find hg binary. Install Mercurial and then press enter...")
		awaitEnter()
	}
}

const hgDefaultPath = `C:\Program Files\Mercurial\hg.exe`

func hgBin() (string, bool) {
	b, err := exec.LookPath("hg")
	if err != nil {
		b = hgDefaultPath
	}
	return b, fileExists(b)
}

func checkGcc() {
	for !fileExists(gccPath) {
		log.Printf("%s doesn't exist. Install gcc and then press enter...", gccPath)
		awaitEnter()
	}
}

func checkoutGo() {
	if fileExists(goroot()) {
		log.Printf("GOROOT %s already exists; skipping hg checkout", goroot())
		return
	}
	log.Printf("Checking out Go source using Mercurial (hg)")

	hg, _ := hgBin()
	cmd := exec.Command(hg, "clone", "https://code.google.com/p/go", "goroot")
	cmd.Dir = home()
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		log.Fatalf("hg clone failed. Is Mercurial installed? Re-run later. Error: %v", err)
	}
	log.Printf("Checked out Go.")
}

func awaitEnter() {
	var buf [1]byte
	os.Stdin.Read(buf[:])
}

func awaitString(want string) bool {
	br := bufio.NewReader(os.Stdin)
	ln, _, _ := br.ReadLine()
	return strings.TrimSpace(string(ln)) == want
}

func fileExists(path string) bool {
	_, err := os.Stat(path)
	return err == nil
}

func check(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func home() string { return os.Getenv("HOMEPATH") }

func goroot() string { return filepath.Join(home(), "goroot") }

func gopath() string { return filepath.Join(home(), "gopath") }

func download(file, url string, wg *sync.WaitGroup) {
	defer wg.Done()

	dst := filepath.Join(home(), "Desktop", file)
	if _, err := os.Stat(dst); err == nil {
		log.Printf("%s already on desktop; skipping", file)
		return
	}

	res, err := http.Get(url)
	if err != nil {
		log.Fatalf("Error fetching %v: %v", url, err)
	}
	tmp := dst + ".tmp"
	os.Remove(tmp)
	os.Remove(dst)
	f, err := os.Create(tmp)
	if err != nil {
		log.Fatal(err)
	}
	n, err := io.Copy(f, res.Body)
	res.Body.Close()
	if err != nil {
		log.Fatalf("Error reading %v: %v", url, err)
	}
	f.Close()
	err = os.Rename(tmp, dst)
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("Downladed %s (%d bytes) to desktop", file, n)
}
<|endoftext|>