<commit_before>package terraform

import (
	"fmt"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/config/module"
)

// NodeApplyableModuleVariable represents a module variable input during
// the apply step.
type NodeApplyableModuleVariable struct {
	PathValue []string
	Config    *config.Variable  // Config is the var in the config
	Value     *config.RawConfig // Value is the value that is set

	Module *module.Tree // Antiquated, want to remove
}

func (n *NodeApplyableModuleVariable) Name() string {
	result := fmt.Sprintf("var.%s", n.Config.Name)
	if len(n.PathValue) > 1 {
		result = fmt.Sprintf("%s.%s", modulePrefixStr(n.PathValue), result)
	}

	return result
}

// GraphNodeSubPath
func (n *NodeApplyableModuleVariable) Path() []string {
	// We execute in the parent scope (above our own module) so that
	// we can access the proper interpolations.
	if len(n.PathValue) > 2 {
		return n.PathValue[:len(n.PathValue)-1]
	}

	return nil
}

// GraphNodeReferenceGlobal
func (n *NodeApplyableModuleVariable) ReferenceGlobal() bool {
	// We have to create fully qualified references because we cross
	// boundaries here: our ReferenceableName is in one path and our
	// References are from another path.
	return true
}

// GraphNodeReferenceable
func (n *NodeApplyableModuleVariable) ReferenceableName() []string {
	return []string{n.Name()}
}

// GraphNodeEvalable
func (n *NodeApplyableModuleVariable) EvalTree() EvalNode {
	// If we have no value, do nothing
	if n.Value == nil {
		return &EvalNoop{}
	}

	// Otherwise, interpolate the value of this variable and set it
	// within the variables mapping.
	var config *ResourceConfig
	variables := make(map[string]interface{})
	return &EvalSequence{
		Nodes: []EvalNode{
			&EvalInterpolate{
				Config: n.Value,
				Output: &config,
			},

			&EvalVariableBlock{
				Config:         &config,
				VariableValues: variables,
			},

			&EvalCoerceMapVariable{
				Variables:  variables,
				ModulePath: n.PathValue,
				ModuleTree: n.Module,
			},

			&EvalTypeCheckVariable{
				Variables:  variables,
				ModulePath: n.PathValue,
				ModuleTree: n.Module,
			},

			&EvalSetVariables{
				Module:    &n.PathValue[len(n.PathValue)-1],
				Variables: variables,
			},
		},
	}
}
<commit_msg>terraform: depend on parent items<commit_after>package terraform

import (
	"fmt"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/config/module"
)

// NodeApplyableModuleVariable represents a module variable input during
// the apply step.
type NodeApplyableModuleVariable struct {
	PathValue []string
	Config    *config.Variable  // Config is the var in the config
	Value     *config.RawConfig // Value is the value that is set

	Module *module.Tree // Antiquated, want to remove
}

func (n *NodeApplyableModuleVariable) Name() string {
	result := fmt.Sprintf("var.%s", n.Config.Name)
	if len(n.PathValue) > 1 {
		result = fmt.Sprintf("%s.%s", modulePrefixStr(n.PathValue), result)
	}

	return result
}

// GraphNodeSubPath
func (n *NodeApplyableModuleVariable) Path() []string {
	// We execute in the parent scope (above our own module) so that
	// we can access the proper interpolations.
	if len(n.PathValue) > 2 {
		return n.PathValue[:len(n.PathValue)-1]
	}

	return nil
}

// GraphNodeReferenceGlobal
func (n *NodeApplyableModuleVariable) ReferenceGlobal() bool {
	// We have to create fully qualified references because we cross
	// boundaries here: our ReferenceableName is in one path and our
	// References are from another path.
	return true
}

// GraphNodeReferenceable
func (n *NodeApplyableModuleVariable) ReferenceableName() []string {
	return []string{n.Name()}
}

// GraphNodeReferencer
func (n *NodeApplyableModuleVariable) References() []string {
	// If we have no value set, we depend on nothing
	if n.Value == nil {
		return nil
	}

	// Can't depend on anything if we're in the root
	path := n.Path()
	if len(path) < 2 {
		return nil
	}

	// Otherwise, we depend on anything that is in our value, but
	// specifically in the namespace of the parent path.
	// Create the prefix based on the path
	prefix := modulePrefixStr(path) + "."
	result := ReferencesFromConfig(n.Value)
	return modulePrefixList(result, prefix)
}

// GraphNodeEvalable
func (n *NodeApplyableModuleVariable) EvalTree() EvalNode {
	// If we have no value, do nothing
	if n.Value == nil {
		return &EvalNoop{}
	}

	// Otherwise, interpolate the value of this variable and set it
	// within the variables mapping.
	var config *ResourceConfig
	variables := make(map[string]interface{})
	return &EvalSequence{
		Nodes: []EvalNode{
			&EvalInterpolate{
				Config: n.Value,
				Output: &config,
			},

			&EvalVariableBlock{
				Config:         &config,
				VariableValues: variables,
			},

			&EvalCoerceMapVariable{
				Variables:  variables,
				ModulePath: n.PathValue,
				ModuleTree: n.Module,
			},

			&EvalTypeCheckVariable{
				Variables:  variables,
				ModulePath: n.PathValue,
				ModuleTree: n.Module,
			},

			&EvalSetVariables{
				Module:    &n.PathValue[len(n.PathValue)-1],
				Variables: variables,
			},
		},
	}
}
<|endoftext|>


<commit_before>package mtp

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/hanwen/go-mtpfs/usb"
)

// An MTP device.
type Device struct {
	h   *usb.DeviceHandle
	dev *usb.Device

	claimed bool

	// split off descriptor?
	devDescr    usb.DeviceDescriptor
	ifaceDescr  usb.InterfaceDescriptor
	sendEp      byte
	fetchEp     byte
	eventEp     byte
	configIndex byte

	// In milliseconds. Defaults to 2 seconds.
	Timeout int

	// Print request/response codes.
	DebugPrint bool

	// Print data as it passes over the USB connection.
	DataPrint bool

	// If set, send header in separate write.
	SeparateHeader bool

	session *sessionData
}

type sessionData struct {
	tid uint32
	sid uint32
}

// RCError are return codes from the Container.Code field.
type RCError uint16

func (e RCError) Error() string {
	n, ok := RC_names[int(e)]
	if ok {
		return n
	}
	return fmt.Sprintf("RetCode %x", uint16(e))
}

// Close releases the interface, and closes the device.
func (d *Device) Close() error {
	if d.h == nil {
		return nil // or error?
	}

	if d.claimed {
		d.h.ReleaseInterface(d.ifaceDescr.InterfaceNumber)
	}
	err := d.h.Close()
	d.h = nil
	return err
}

// Done releases the libusb device reference.
func (d *Device) Done() {
	d.dev.Unref()
	d.dev = nil
}

// Open opens an MTP device.
func (d *Device) Open() error {
	if d.Timeout == 0 {
		d.Timeout = 2000
	}

	if d.h != nil {
		return fmt.Errorf("already open")
	}

	var err error
	d.h, err = d.dev.Open()
	if err != nil {
		return err
	}

	iface, err := d.h.GetStringDescriptorASCII(d.ifaceDescr.InterfaceStringIndex)
	if err != nil {
		d.Close()
		return err
	}

	if !strings.Contains(iface, "MTP") {
		d.Close()
		return fmt.Errorf("has no MTP in interface string")
	}
	return nil
}

// Id is the manufacturer + product + serial
func (d *Device) Id() (string, error) {
	if d.h == nil {
		return "", fmt.Errorf("device not open")
	}

	var ids []string
	for _, b := range []byte{
		d.devDescr.Manufacturer,
		d.devDescr.Product,
		d.devDescr.SerialNumber} {
		s, err := d.h.GetStringDescriptorASCII(b)
		if err != nil {
			return "", err
		}
		ids = append(ids, s)
	}

	return strings.Join(ids, " "), nil
}

func (d *Device) sendReq(req *Container) error {
	c := usbBulkContainer{
		usbBulkHeader: usbBulkHeader{
			Length:        uint32(usbHdrLen + 4*len(req.Param)),
			Type:          USB_CONTAINER_COMMAND,
			Code:          req.Code,
			TransactionID: req.TransactionID,
		},
	}
	for i := range req.Param {
		c.Param[i] = req.Param[i]
	}

	var wData [usbBulkLen]byte
	buf := bytes.NewBuffer(wData[:0])

	err := binary.Write(buf, binary.LittleEndian, c)
	if err != nil {
		panic(err)
	}

	d.dataPrint(d.sendEp, buf.Bytes())
	_, err = d.h.BulkTransfer(d.sendEp, buf.Bytes(), d.Timeout)
	if err != nil {
		return err
	}
	return nil
}

const packetSize = 512

// Fetches one USB packet. The header is split off, and the remainder is returned.
// dest should be at least 512bytes.
func (d *Device) fetchPacket(dest []byte, header *usbBulkHeader) (rest []byte, err error) {
	n, err := d.h.BulkTransfer(d.fetchEp, dest[:packetSize], d.Timeout)
	if n > 0 {
		d.dataPrint(d.fetchEp, dest[:n])
	}

	if err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(dest[:n])
	err = binary.Read(buf, binary.LittleEndian, header)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func (d *Device) decodeRep(h *usbBulkHeader, rest []byte, rep *Container) error {
	if h.Type != USB_CONTAINER_RESPONSE {
		return fmt.Errorf("got type %d in response", h.Type)
	}

	rep.Code = h.Code
	if rep.Code != RC_OK {
		return RCError(rep.Code)
	}
	rep.TransactionID = h.TransactionID

	restLen := int(h.Length) - usbHdrLen
	if restLen != len(rest) {
		return fmt.Errorf("header specified 0x%x bytes, but have 0x%x",
			restLen, len(rest))
	}
	nParam := restLen / 4
	for i := 0; i < nParam; i++ {
		rep.Param = append(rep.Param, byteOrder.Uint32(rest[4*i:]))
	}

	return nil
}

// Runs a single MTP transaction. dest and src cannot be specified at
// the same time.  The request should fill out Code and Param as
// necessary. The response is provided here, but usually only the
// return code is of interest.  If the return code is an error, this
// function will return an RCError instance.
func (d *Device) RunTransaction(req *Container, rep *Container,
	dest io.Writer, src io.Reader, writeSize int64) error {
	if d.session != nil {
		req.SessionID = d.session.sid
		req.TransactionID = d.session.tid
		d.session.tid++
	}

	if d.DebugPrint {
		fmt.Printf("request %s %v\n", OC_names[int(req.Code)], req.Param)
	}

	err := d.sendReq(req)
	if err != nil {
		return err
	}

	if src != nil {
		hdr := usbBulkHeader{
			Type:          USB_CONTAINER_DATA,
			Code:          req.Code,
			Length:        uint32(writeSize),
			TransactionID: req.TransactionID,
		}

		_, err := d.bulkWrite(&hdr, src, writeSize)
		if err != nil {
			d.Close()
			return err
		}
	}
	var data [packetSize]byte
	h := &usbBulkHeader{}
	rest, err := d.fetchPacket(data[:], h)
	if err != nil {
		return err
	}
	if h.Type == USB_CONTAINER_DATA {
		if dest == nil {
			d.Close()
			return fmt.Errorf("no sink for data")
		}
		if d.DebugPrint {
			fmt.Printf("data %d\n", h.Length)
		}

		size := int(h.Length)
		dest.Write(rest)
		size -= len(rest) + usbHdrLen
		if size > 0 {
			_, err = d.bulkRead(dest)
			if err != nil {
				return err
			}
		}

		h = &usbBulkHeader{}
		rest, err = d.fetchPacket(data[:], h)
	}

	err = d.decodeRep(h, rest, rep)
	if d.DebugPrint {
		fmt.Printf("rep %s\n", RC_names[int(rep.Code)])
	}
	if err != nil {
		return err
	}
	if d.session != nil && rep.TransactionID != req.TransactionID {
		return fmt.Errorf("transaction ID mismatch got %x want %x",
			rep.TransactionID, req.TransactionID)
	}
	rep.SessionID = req.SessionID
	return nil
}

// Prints data going over the USB connection.
func (d *Device) dataPrint(ep byte, data []byte) {
	if !d.DataPrint {
		return
	}
	dir := "send"
	if 0 != ep&usb.ENDPOINT_IN {
		dir = "recv"
	}
	fmt.Fprintf(os.Stderr, "%s: 0x%x bytes with ep 0x%x:\n", dir, len(data), ep)
	hexDump(data)
}

// The linux usb stack can send 16kb per call, according to libusb.
const rwBufSize = 0x4000

// bulkWrite returns the number of non-header bytes written.
func (d *Device) bulkWrite(hdr *usbBulkHeader, r io.Reader, size int64) (n int64, err error) {
	if hdr != nil {
		if size+usbHdrLen > 0xFFFFFFFF {
			hdr.Length = 0xFFFFFFFF
		} else {
			hdr.Length = uint32(size + usbHdrLen)
		}

		var packetArr [packetSize]byte
		var packet []byte
		if d.SeparateHeader {
			packet = packetArr[:usbHdrLen]
		} else {
			packet = packetArr[:]
		}

		buf := bytes.NewBuffer(packet[:0])
		binary.Write(buf, byteOrder, hdr)
		cpSize := int64(len(packet) - usbHdrLen)
		if cpSize > size {
			cpSize = size
		}

		_, err = io.CopyN(buf, r, cpSize)
		d.dataPrint(d.sendEp, buf.Bytes())
		_, err = d.h.BulkTransfer(d.sendEp, buf.Bytes(), d.Timeout)
		if err != nil {
			return cpSize, err
		}
		size -= cpSize
		n += cpSize
	}

	var buf [rwBufSize]byte
	var lastTransfer int
	for size > 0 {
		var m int
		toread := buf[:]
		if int64(len(toread)) > size {
			toread = buf[:int(size)]
		}

		m, err = r.Read(toread)
		if err != nil {
			break
		}
		size -= int64(m)

		d.dataPrint(d.sendEp, buf[:m])
		lastTransfer, err = d.h.BulkTransfer(d.sendEp, buf[:m], d.Timeout)
		n += int64(lastTransfer)

		if err != nil || lastTransfer == 0 {
			break
		}
	}
	if lastTransfer%packetSize == 0 {
		// write a short packet just to be sure.
		d.h.BulkTransfer(d.sendEp, buf[:0], d.Timeout)
	}

	return n, err
}

func (d *Device) bulkRead(w io.Writer) (n int64, err error) {
	var buf [rwBufSize]byte
	var lastRead int
	for {
		toread := buf[:]
		lastRead, err = d.h.BulkTransfer(d.fetchEp, toread, d.Timeout)
		if err != nil {
			break
		}
		if lastRead > 0 {
			d.dataPrint(d.fetchEp, buf[:lastRead])

			w, err := w.Write(buf[:lastRead])
			n += int64(w)
			if err != nil {
				break
			}
		}
		if lastRead < len(toread) {
			// short read.
			break
		}
	}
	if lastRead%packetSize == 0 {
		// Null read.
		d.h.BulkTransfer(d.fetchEp, buf[:0], d.Timeout)
	}
	return n, err
}
<commit_msg>Add return params in DebugPrint output.<commit_after>package mtp

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/hanwen/go-mtpfs/usb"
)

// An MTP device.
type Device struct {
	h   *usb.DeviceHandle
	dev *usb.Device

	claimed bool

	// split off descriptor?
	devDescr    usb.DeviceDescriptor
	ifaceDescr  usb.InterfaceDescriptor
	sendEp      byte
	fetchEp     byte
	eventEp     byte
	configIndex byte

	// In milliseconds. Defaults to 2 seconds.
	Timeout int

	// Print request/response codes.
	DebugPrint bool

	// Print data as it passes over the USB connection.
	DataPrint bool

	// If set, send header in separate write.
	SeparateHeader bool

	session *sessionData
}

type sessionData struct {
	tid uint32
	sid uint32
}

// RCError are return codes from the Container.Code field.
type RCError uint16

func (e RCError) Error() string {
	n, ok := RC_names[int(e)]
	if ok {
		return n
	}
	return fmt.Sprintf("RetCode %x", uint16(e))
}

// Close releases the interface, and closes the device.
func (d *Device) Close() error {
	if d.h == nil {
		return nil // or error?
	}

	if d.claimed {
		d.h.ReleaseInterface(d.ifaceDescr.InterfaceNumber)
	}
	err := d.h.Close()
	d.h = nil
	return err
}

// Done releases the libusb device reference.
func (d *Device) Done() {
	d.dev.Unref()
	d.dev = nil
}

// Open opens an MTP device.
func (d *Device) Open() error {
	if d.Timeout == 0 {
		d.Timeout = 2000
	}

	if d.h != nil {
		return fmt.Errorf("already open")
	}

	var err error
	d.h, err = d.dev.Open()
	if err != nil {
		return err
	}

	iface, err := d.h.GetStringDescriptorASCII(d.ifaceDescr.InterfaceStringIndex)
	if err != nil {
		d.Close()
		return err
	}

	if !strings.Contains(iface, "MTP") {
		d.Close()
		return fmt.Errorf("has no MTP in interface string")
	}
	return nil
}

// Id is the manufacturer + product + serial
func (d *Device) Id() (string, error) {
	if d.h == nil {
		return "", fmt.Errorf("device not open")
	}

	var ids []string
	for _, b := range []byte{
		d.devDescr.Manufacturer,
		d.devDescr.Product,
		d.devDescr.SerialNumber} {
		s, err := d.h.GetStringDescriptorASCII(b)
		if err != nil {
			return "", err
		}
		ids = append(ids, s)
	}

	return strings.Join(ids, " "), nil
}

func (d *Device) sendReq(req *Container) error {
	c := usbBulkContainer{
		usbBulkHeader: usbBulkHeader{
			Length:        uint32(usbHdrLen + 4*len(req.Param)),
			Type:          USB_CONTAINER_COMMAND,
			Code:          req.Code,
			TransactionID: req.TransactionID,
		},
	}
	for i := range req.Param {
		c.Param[i] = req.Param[i]
	}

	var wData [usbBulkLen]byte
	buf := bytes.NewBuffer(wData[:0])

	err := binary.Write(buf, binary.LittleEndian, c)
	if err != nil {
		panic(err)
	}

	d.dataPrint(d.sendEp, buf.Bytes())
	_, err = d.h.BulkTransfer(d.sendEp, buf.Bytes(), d.Timeout)
	if err != nil {
		return err
	}
	return nil
}

const packetSize = 512

// Fetches one USB packet. The header is split off, and the remainder is returned.
// dest should be at least 512bytes.
func (d *Device) fetchPacket(dest []byte, header *usbBulkHeader) (rest []byte, err error) {
	n, err := d.h.BulkTransfer(d.fetchEp, dest[:packetSize], d.Timeout)
	if n > 0 {
		d.dataPrint(d.fetchEp, dest[:n])
	}

	if err != nil {
		return nil, err
	}

	buf := bytes.NewBuffer(dest[:n])
	err = binary.Read(buf, binary.LittleEndian, header)
	if err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}

func (d *Device) decodeRep(h *usbBulkHeader, rest []byte, rep *Container) error {
	if h.Type != USB_CONTAINER_RESPONSE {
		return fmt.Errorf("got type %d in response", h.Type)
	}

	rep.Code = h.Code
	if rep.Code != RC_OK {
		return RCError(rep.Code)
	}
	rep.TransactionID = h.TransactionID

	restLen := int(h.Length) - usbHdrLen
	if restLen != len(rest) {
		return fmt.Errorf("header specified 0x%x bytes, but have 0x%x",
			restLen, len(rest))
	}
	nParam := restLen / 4
	for i := 0; i < nParam; i++ {
		rep.Param = append(rep.Param, byteOrder.Uint32(rest[4*i:]))
	}

	return nil
}

// Runs a single MTP transaction. dest and src cannot be specified at
// the same time.  The request should fill out Code and Param as
// necessary. The response is provided here, but usually only the
// return code is of interest.  If the return code is an error, this
// function will return an RCError instance.
func (d *Device) RunTransaction(req *Container, rep *Container,
	dest io.Writer, src io.Reader, writeSize int64) error {
	if d.session != nil {
		req.SessionID = d.session.sid
		req.TransactionID = d.session.tid
		d.session.tid++
	}

	if d.DebugPrint {
		fmt.Printf("request %s %v\n", OC_names[int(req.Code)], req.Param)
	}

	err := d.sendReq(req)
	if err != nil {
		return err
	}

	if src != nil {
		hdr := usbBulkHeader{
			Type:          USB_CONTAINER_DATA,
			Code:          req.Code,
			Length:        uint32(writeSize),
			TransactionID: req.TransactionID,
		}

		_, err := d.bulkWrite(&hdr, src, writeSize)
		if err != nil {
			d.Close()
			return err
		}
	}
	var data [packetSize]byte
	h := &usbBulkHeader{}
	rest, err := d.fetchPacket(data[:], h)
	if err != nil {
		return err
	}
	if h.Type == USB_CONTAINER_DATA {
		if dest == nil {
			d.Close()
			return fmt.Errorf("no sink for data")
		}
		if d.DebugPrint {
			fmt.Printf("data %d\n", h.Length)
		}

		size := int(h.Length)
		dest.Write(rest)
		size -= len(rest) + usbHdrLen
		if size > 0 {
			_, err = d.bulkRead(dest)
			if err != nil {
				return err
			}
		}

		h = &usbBulkHeader{}
		rest, err = d.fetchPacket(data[:], h)
	}

	err = d.decodeRep(h, rest, rep)
	if d.DebugPrint {
		fmt.Printf("rep %s %v\n", RC_names[int(rep.Code)], rep.Param)
	}
	if err != nil {
		return err
	}
	if d.session != nil && rep.TransactionID != req.TransactionID {
		return fmt.Errorf("transaction ID mismatch got %x want %x",
			rep.TransactionID, req.TransactionID)
	}
	rep.SessionID = req.SessionID
	return nil
}

// Prints data going over the USB connection.
func (d *Device) dataPrint(ep byte, data []byte) {
	if !d.DataPrint {
		return
	}
	dir := "send"
	if 0 != ep&usb.ENDPOINT_IN {
		dir = "recv"
	}
	fmt.Fprintf(os.Stderr, "%s: 0x%x bytes with ep 0x%x:\n", dir, len(data), ep)
	hexDump(data)
}

// The linux usb stack can send 16kb per call, according to libusb.
const rwBufSize = 0x4000

// bulkWrite returns the number of non-header bytes written.
func (d *Device) bulkWrite(hdr *usbBulkHeader, r io.Reader, size int64) (n int64, err error) {
	if hdr != nil {
		if size+usbHdrLen > 0xFFFFFFFF {
			hdr.Length = 0xFFFFFFFF
		} else {
			hdr.Length = uint32(size + usbHdrLen)
		}

		var packetArr [packetSize]byte
		var packet []byte
		if d.SeparateHeader {
			packet = packetArr[:usbHdrLen]
		} else {
			packet = packetArr[:]
		}

		buf := bytes.NewBuffer(packet[:0])
		binary.Write(buf, byteOrder, hdr)
		cpSize := int64(len(packet) - usbHdrLen)
		if cpSize > size {
			cpSize = size
		}

		_, err = io.CopyN(buf, r, cpSize)
		d.dataPrint(d.sendEp, buf.Bytes())
		_, err = d.h.BulkTransfer(d.sendEp, buf.Bytes(), d.Timeout)
		if err != nil {
			return cpSize, err
		}
		size -= cpSize
		n += cpSize
	}

	var buf [rwBufSize]byte
	var lastTransfer int
	for size > 0 {
		var m int
		toread := buf[:]
		if int64(len(toread)) > size {
			toread = buf[:int(size)]
		}

		m, err = r.Read(toread)
		if err != nil {
			break
		}
		size -= int64(m)

		d.dataPrint(d.sendEp, buf[:m])
		lastTransfer, err = d.h.BulkTransfer(d.sendEp, buf[:m], d.Timeout)
		n += int64(lastTransfer)

		if err != nil || lastTransfer == 0 {
			break
		}
	}
	if lastTransfer%packetSize == 0 {
		// write a short packet just to be sure.
		d.h.BulkTransfer(d.sendEp, buf[:0], d.Timeout)
	}

	return n, err
}

func (d *Device) bulkRead(w io.Writer) (n int64, err error) {
	var buf [rwBufSize]byte
	var lastRead int
	for {
		toread := buf[:]
		lastRead, err = d.h.BulkTransfer(d.fetchEp, toread, d.Timeout)
		if err != nil {
			break
		}
		if lastRead > 0 {
			d.dataPrint(d.fetchEp, buf[:lastRead])

			w, err := w.Write(buf[:lastRead])
			n += int64(w)
			if err != nil {
				break
			}
		}
		if lastRead < len(toread) {
			// short read.
			break
		}
	}
	if lastRead%packetSize == 0 {
		// Null read.
		d.h.BulkTransfer(d.fetchEp, buf[:0], d.Timeout)
	}
	return n, err
}
<|endoftext|>


<commit_before>package mux

import (
	"net/http"
	"regexp"
)

type RecoverHandler func(*http.Request, http.ResponseWriter, interface{}) interface{}

type RequestProcessor func(*http.Request, http.ResponseWriter, *Context) (*http.Request, bool)

type Handler func(http.ResponseWriter, *http.Request, *Context)

type handlerInfo struct {
	/* TODO: Add support for patterns specifing a host */
	re      *regexp.Regexp
	handler Handler
}

type Mux struct {
	handlers          []*handlerInfo
	RequestProcessors []RequestProcessor
	RecoverHandlers   []RecoverHandler
}

func (mux *Mux) HandleMuxFunc(pattern string, handler Handler) {
	info := &handlerInfo{
		re:      regexp.MustCompile(pattern),
		handler: handler,
	}
	mux.handlers = append(mux.handlers, info)
}

func (mux *Mux) AddRequestProcessor(rp RequestProcessor) {
	mux.RequestProcessors = append(mux.RequestProcessors, rp)
}

func (mux *Mux) AddRecoverHandler(rh RecoverHandler) {
	mux.RecoverHandlers = append(mux.RecoverHandlers, rh)
}

func (mux *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			for _, v := range mux.RecoverHandlers {
				err = v(r, w, err)
				if err == nil {
					break
				}
			}
			if err != nil {
				panic(err)
			}
		}
	}()
	stop := false
	ctx := &Context{}
	for _, v := range mux.RequestProcessors {
		r, stop = v(r, w, ctx)
		if stop {
			break
		}
	}
	if !stop {
		/* Try mux handlers first */
		for _, v := range mux.handlers {
			if submatches := v.re.FindStringSubmatch(r.URL.Path); submatches != nil {
				params := map[string]string{}
				for ii, n := range v.re.SubexpNames() {
					if n != "" {
						params[n] = submatches[ii]
					}
				}
				ctx.submatches = submatches
				ctx.params = params
				v.handler(w, r, ctx)
				stop = true
				break
			}
		}
		if !stop {
			http.DefaultServeMux.ServeHTTP(w, r)
		}
	}
}

func New() *Mux {
	return &Mux{}
}

type Context struct {
	submatches []string
	params     map[string]string
}

func (c *Context) Count() int {
	return len(c.submatches)
}

func (c *Context) IndexValue(idx int) string {
	if idx < len(c.submatches) {
		return c.submatches[idx]
	}
	return ""
}

func (c *Context) ParamValue(name string) string {
	return c.params[name]
}
<commit_msg>Add a Data parameter to the Context<commit_after>package mux

import (
	"net/http"
	"regexp"
)

type RecoverHandler func(*http.Request, http.ResponseWriter, interface{}) interface{}

type RequestProcessor func(*http.Request, http.ResponseWriter, *Context) (*http.Request, bool)

type Handler func(http.ResponseWriter, *http.Request, *Context)

type handlerInfo struct {
	/* TODO: Add support for patterns specifing a host */
	re      *regexp.Regexp
	handler Handler
}

type Mux struct {
	handlers          []*handlerInfo
	RequestProcessors []RequestProcessor
	RecoverHandlers   []RecoverHandler
}

func (mux *Mux) HandleMuxFunc(pattern string, handler Handler) {
	info := &handlerInfo{
		re:      regexp.MustCompile(pattern),
		handler: handler,
	}
	mux.handlers = append(mux.handlers, info)
}

func (mux *Mux) AddRequestProcessor(rp RequestProcessor) {
	mux.RequestProcessors = append(mux.RequestProcessors, rp)
}

func (mux *Mux) AddRecoverHandler(rh RecoverHandler) {
	mux.RecoverHandlers = append(mux.RecoverHandlers, rh)
}

func (mux *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			for _, v := range mux.RecoverHandlers {
				err = v(r, w, err)
				if err == nil {
					break
				}
			}
			if err != nil {
				panic(err)
			}
		}
	}()
	stop := false
	ctx := &Context{}
	for _, v := range mux.RequestProcessors {
		r, stop = v(r, w, ctx)
		if stop {
			break
		}
	}
	if !stop {
		/* Try mux handlers first */
		for _, v := range mux.handlers {
			if submatches := v.re.FindStringSubmatch(r.URL.Path); submatches != nil {
				params := map[string]string{}
				for ii, n := range v.re.SubexpNames() {
					if n != "" {
						params[n] = submatches[ii]
					}
				}
				ctx.submatches = submatches
				ctx.params = params
				v.handler(w, r, ctx)
				stop = true
				break
			}
		}
		if !stop {
			http.DefaultServeMux.ServeHTTP(w, r)
		}
	}
}

func New() *Mux {
	return &Mux{}
}

type Context struct {
	submatches []string
	params     map[string]string
	Data interface{} /* Left to the user */
}

func (c *Context) Count() int {
	return len(c.submatches)
}

func (c *Context) IndexValue(idx int) string {
	if idx < len(c.submatches) {
		return c.submatches[idx]
	}
	return ""
}

func (c *Context) ParamValue(name string) string {
	return c.params[name]
}
<|endoftext|>


<commit_before>// Package new generates micro service templates
package new

import (
	"fmt"
	"go/build"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"text/template"
	"time"

	"github.com/micro/cli/v2"
	tmpl "github.com/micro/micro/v2/internal/template"
	"github.com/micro/micro/v2/internal/usage"
	"github.com/xlab/treeprint"
)

func protoComments(goDir, alias string) []string {
	return []string{
		"\ndownload protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install:\n",
		"visit https://github.com/protocolbuffers/protobuf/releases",
		"\ndownload protobuf for micro:\n",
		"go get -u github.com/golang/protobuf/proto",
		"go get -u github.com/golang/protobuf/protoc-gen-go",
		"go get github.com/micro/micro/v2/cmd/protoc-gen-micro",
		"\ncompile the proto file " + alias + ".proto:\n",
		"cd " + goDir,
		"protoc --proto_path=.:$GOPATH/src --go_out=. --micro_out=. proto/" + alias + "/" + alias + ".proto\n",
	}
}

type config struct {
	// foo
	Alias string
	// micro new example -type
	Command string
	// go.micro
	Namespace string
	// api, service, web, function
	Type string
	// go.micro.service.foo
	FQDN string
	// github.com/micro/foo
	Dir string
	// $GOPATH/src/github.com/micro/foo
	GoDir string
	// $GOPATH
	GoPath string
	// UseGoPath
	UseGoPath bool
	// Files
	Files []file
	// Comments
	Comments []string
	// Plugins registry=etcd:broker=nats
	Plugins []string
}

type file struct {
	Path string
	Tmpl string
}

func write(c config, file, tmpl string) error {
	fn := template.FuncMap{
		"title": strings.Title,
	}

	f, err := os.Create(file)
	if err != nil {
		return err
	}
	defer f.Close()

	t, err := template.New("f").Funcs(fn).Parse(tmpl)
	if err != nil {
		return err
	}

	return t.Execute(f, c)
}

func create(c config) error {
	// check if dir exists
	if _, err := os.Stat(c.GoDir); !os.IsNotExist(err) {
		return fmt.Errorf("%s already exists", c.GoDir)
	}

	// create usage report
	u := usage.New("new")
	// a single request/service
	u.Metrics.Count["requests"] = uint64(1)
	u.Metrics.Count["services"] = uint64(1)
	// send report
	go usage.Report(u)

	// just wait
	<-time.After(time.Millisecond * 250)

	fmt.Printf("Creating service %s in %s\n\n", c.FQDN, c.GoDir)

	t := treeprint.New()

	nodes := map[string]treeprint.Tree{}
	nodes[c.GoDir] = t

	// write the files
	for _, file := range c.Files {
		f := filepath.Join(c.GoDir, file.Path)
		dir := filepath.Dir(f)

		b, ok := nodes[dir]
		if !ok {
			d, _ := filepath.Rel(c.GoDir, dir)
			b = t.AddBranch(d)
			nodes[dir] = b
		}

		if _, err := os.Stat(dir); os.IsNotExist(err) {
			if err := os.MkdirAll(dir, 0755); err != nil {
				return err
			}
		}

		p := filepath.Base(f)

		b.AddNode(p)
		if err := write(c, f, file.Tmpl); err != nil {
			return err
		}
	}

	// print tree
	fmt.Println(t.String())

	for _, comment := range c.Comments {
		fmt.Println(comment)
	}

	// just wait
	<-time.After(time.Millisecond * 250)

	return nil
}

func run(ctx *cli.Context) {
	namespace := ctx.String("namespace")
	alias := ctx.String("alias")
	fqdn := ctx.String("fqdn")
	atype := ctx.String("type")
	dir := ctx.Args().First()
	useGoPath := ctx.Bool("gopath")
	useGoModule := os.Getenv("GO111MODULE")
	var plugins []string

	if len(dir) == 0 {
		fmt.Println("specify service name")
		return
	}

	if len(namespace) == 0 {
		fmt.Println("namespace not defined")
		return
	}

	if len(atype) == 0 {
		fmt.Println("type not defined")
		return
	}

	// set the command
	command := fmt.Sprintf("micro new %s", dir)
	if len(namespace) > 0 {
		command += " --namespace=" + namespace
	}
	if len(alias) > 0 {
		command += " --alias=" + alias
	}
	if len(fqdn) > 0 {
		command += " --fqdn=" + fqdn
	}
	if len(atype) > 0 {
		command += " --type=" + atype
	}
	if plugins := ctx.StringSlice("plugin"); len(plugins) > 0 {
		command += " --plugin=" + strings.Join(plugins, ":")
	}

	// check if the path is absolute, we don't want this
	// we want to a relative path so we can install in GOPATH
	if path.IsAbs(dir) {
		fmt.Println("require relative path as service will be installed in GOPATH")
		return
	}

	var goPath string
	var goDir string

	// only set gopath if told to use it
	if useGoPath {
		goPath = build.Default.GOPATH

		// don't know GOPATH, runaway....
		if len(goPath) == 0 {
			fmt.Println("unknown GOPATH")
			return
		}

		// attempt to split path if not windows
		if runtime.GOOS == "windows" {
			goPath = strings.Split(goPath, ";")[0]
		} else {
			goPath = strings.Split(goPath, ":")[0]
		}
		goDir = filepath.Join(goPath, "src", path.Clean(dir))
	} else {
		goDir = path.Clean(dir)
	}

	if len(alias) == 0 {
		// set as last part
		alias = filepath.Base(dir)
		// strip hyphens
		parts := strings.Split(alias, "-")
		alias = parts[0]
	}

	if len(fqdn) == 0 {
		fqdn = strings.Join([]string{namespace, atype, alias}, ".")
	}

	for _, plugin := range ctx.StringSlice("plugin") {
		// registry=etcd:broker=nats
		for _, p := range strings.Split(plugin, ":") {
			// registry=etcd
			parts := strings.Split(p, "=")
			if len(parts) < 2 {
				continue
			}
			plugins = append(plugins, path.Join(parts...))
		}
	}

	var c config

	switch atype {
	case "function":
		// create service config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainFNC},
				{"generate.go", tmpl.GenerateFile},
				{"plugin.go", tmpl.Plugin},
				{"handler/" + alias + ".go", tmpl.HandlerFNC},
				{"subscriber/" + alias + ".go", tmpl.SubscriberFNC},
				{"proto/" + alias + "/" + alias + ".proto", tmpl.ProtoFNC},
				{"Dockerfile", tmpl.DockerFNC},
				{"Makefile", tmpl.Makefile},
				{"README.md", tmpl.ReadmeFNC},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: protoComments(goDir, alias),
		}
	case "service":
		// create service config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainSRV},
				{"generate.go", tmpl.GenerateFile},
				{"plugin.go", tmpl.Plugin},
				{"handler/" + alias + ".go", tmpl.HandlerSRV},
				{"subscriber/" + alias + ".go", tmpl.SubscriberSRV},
				{"proto/" + alias + "/" + alias + ".proto", tmpl.ProtoSRV},
				{"Dockerfile", tmpl.DockerSRV},
				{"Makefile", tmpl.Makefile},
				{"README.md", tmpl.Readme},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: protoComments(goDir, alias),
		}
	case "api":
		// create api config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainAPI},
				{"generate.go", tmpl.GenerateFile},
				{"plugin.go", tmpl.Plugin},
				{"client/" + alias + ".go", tmpl.WrapperAPI},
				{"handler/" + alias + ".go", tmpl.HandlerAPI},
				{"proto/" + alias + "/" + alias + ".proto", tmpl.ProtoAPI},
				{"Makefile", tmpl.Makefile},
				{"Dockerfile", tmpl.DockerSRV},
				{"README.md", tmpl.Readme},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: protoComments(goDir, alias),
		}
	case "web":
		// create service config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainWEB},
				{"plugin.go", tmpl.Plugin},
				{"handler/handler.go", tmpl.HandlerWEB},
				{"html/index.html", tmpl.HTMLWEB},
				{"Dockerfile", tmpl.DockerWEB},
				{"Makefile", tmpl.Makefile},
				{"README.md", tmpl.Readme},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: []string{},
		}
	default:
		fmt.Println("Unknown type", atype)
		return
	}

	// set gomodule
	if useGoModule != "off" {
		c.Files = append(c.Files, file{"go.mod", tmpl.Module})
	}

	if err := create(c); err != nil {
		fmt.Println(err)
		return
	}
}

func Commands() []*cli.Command {
	return []*cli.Command{
		{
			Name:  "new",
			Usage: "Create a service template",
			Flags: []cli.Flag{
				&cli.StringFlag{
					Name:  "namespace",
					Usage: "Namespace for the service e.g com.example",
					Value: "go.micro",
				},
				&cli.StringFlag{
					Name:  "type",
					Usage: "Type of service e.g api, function, service, web",
					Value: "service",
				},
				&cli.StringFlag{
					Name:  "fqdn",
					Usage: "FQDN of service e.g com.example.service.service (defaults to namespace.type.alias)",
				},
				&cli.StringFlag{
					Name:  "alias",
					Usage: "Alias is the short name used as part of combined name if specified",
				},
				&cli.StringSliceFlag{
					Name:  "plugin",
					Usage: "Specify plugins e.g --plugin=registry=etcd:broker=nats or use flag multiple times",
				},
				&cli.BoolFlag{
					Name:  "gopath",
					Usage: "Create the service in the gopath.",
				},
			},
			Action: func(c *cli.Context) error {
				run(c)
				return nil
			},
		},
	}
}
<commit_msg>fix: fix docs with error order of command generated by micro new command (#866)<commit_after>// Package new generates micro service templates
package new

import (
	"fmt"
	"go/build"
	"os"
	"path"
	"path/filepath"
	"runtime"
	"strings"
	"text/template"
	"time"

	"github.com/micro/cli/v2"
	tmpl "github.com/micro/micro/v2/internal/template"
	"github.com/micro/micro/v2/internal/usage"
	"github.com/xlab/treeprint"
)

func protoComments(goDir, alias string) []string {
	return []string{
		"\ndownload protoc zip packages (protoc-$VERSION-$PLATFORM.zip) and install:\n",
		"visit https://github.com/protocolbuffers/protobuf/releases",
		"\ndownload protobuf for micro:\n",
		"go get -u github.com/golang/protobuf/proto",
		"go get -u github.com/golang/protobuf/protoc-gen-go",
		"go get github.com/micro/micro/v2/cmd/protoc-gen-micro",
		"\ncompile the proto file " + alias + ".proto:\n",
		"cd " + goDir,
		"protoc --proto_path=.:$GOPATH/src --go_out=. --micro_out=. proto/" + alias + "/" + alias + ".proto\n",
	}
}

type config struct {
	// foo
	Alias string
	// micro new example -type
	Command string
	// go.micro
	Namespace string
	// api, service, web, function
	Type string
	// go.micro.service.foo
	FQDN string
	// github.com/micro/foo
	Dir string
	// $GOPATH/src/github.com/micro/foo
	GoDir string
	// $GOPATH
	GoPath string
	// UseGoPath
	UseGoPath bool
	// Files
	Files []file
	// Comments
	Comments []string
	// Plugins registry=etcd:broker=nats
	Plugins []string
}

type file struct {
	Path string
	Tmpl string
}

func write(c config, file, tmpl string) error {
	fn := template.FuncMap{
		"title": strings.Title,
	}

	f, err := os.Create(file)
	if err != nil {
		return err
	}
	defer f.Close()

	t, err := template.New("f").Funcs(fn).Parse(tmpl)
	if err != nil {
		return err
	}

	return t.Execute(f, c)
}

func create(c config) error {
	// check if dir exists
	if _, err := os.Stat(c.GoDir); !os.IsNotExist(err) {
		return fmt.Errorf("%s already exists", c.GoDir)
	}

	// create usage report
	u := usage.New("new")
	// a single request/service
	u.Metrics.Count["requests"] = uint64(1)
	u.Metrics.Count["services"] = uint64(1)
	// send report
	go usage.Report(u)

	// just wait
	<-time.After(time.Millisecond * 250)

	fmt.Printf("Creating service %s in %s\n\n", c.FQDN, c.GoDir)

	t := treeprint.New()

	nodes := map[string]treeprint.Tree{}
	nodes[c.GoDir] = t

	// write the files
	for _, file := range c.Files {
		f := filepath.Join(c.GoDir, file.Path)
		dir := filepath.Dir(f)

		b, ok := nodes[dir]
		if !ok {
			d, _ := filepath.Rel(c.GoDir, dir)
			b = t.AddBranch(d)
			nodes[dir] = b
		}

		if _, err := os.Stat(dir); os.IsNotExist(err) {
			if err := os.MkdirAll(dir, 0755); err != nil {
				return err
			}
		}

		p := filepath.Base(f)

		b.AddNode(p)
		if err := write(c, f, file.Tmpl); err != nil {
			return err
		}
	}

	// print tree
	fmt.Println(t.String())

	for _, comment := range c.Comments {
		fmt.Println(comment)
	}

	// just wait
	<-time.After(time.Millisecond * 250)

	return nil
}

func run(ctx *cli.Context) {
	namespace := ctx.String("namespace")
	alias := ctx.String("alias")
	fqdn := ctx.String("fqdn")
	atype := ctx.String("type")
	dir := ctx.Args().First()
	useGoPath := ctx.Bool("gopath")
	useGoModule := os.Getenv("GO111MODULE")
	var plugins []string

	if len(dir) == 0 {
		fmt.Println("specify service name")
		return
	}

	if len(namespace) == 0 {
		fmt.Println("namespace not defined")
		return
	}

	if len(atype) == 0 {
		fmt.Println("type not defined")
		return
	}

	// set the command
	command := "micro new"
	if len(namespace) > 0 {
		command += " --namespace=" + namespace
	}
	if len(alias) > 0 {
		command += " --alias=" + alias
	}
	if len(fqdn) > 0 {
		command += " --fqdn=" + fqdn
	}
	if len(atype) > 0 {
		command += " --type=" + atype
	}
	if plugins := ctx.StringSlice("plugin"); len(plugins) > 0 {
		command += " --plugin=" + strings.Join(plugins, ":")
	}
	command += " " + dir

	// check if the path is absolute, we don't want this
	// we want to a relative path so we can install in GOPATH
	if path.IsAbs(dir) {
		fmt.Println("require relative path as service will be installed in GOPATH")
		return
	}

	var goPath string
	var goDir string

	// only set gopath if told to use it
	if useGoPath {
		goPath = build.Default.GOPATH

		// don't know GOPATH, runaway....
		if len(goPath) == 0 {
			fmt.Println("unknown GOPATH")
			return
		}

		// attempt to split path if not windows
		if runtime.GOOS == "windows" {
			goPath = strings.Split(goPath, ";")[0]
		} else {
			goPath = strings.Split(goPath, ":")[0]
		}
		goDir = filepath.Join(goPath, "src", path.Clean(dir))
	} else {
		goDir = path.Clean(dir)
	}

	if len(alias) == 0 {
		// set as last part
		alias = filepath.Base(dir)
		// strip hyphens
		parts := strings.Split(alias, "-")
		alias = parts[0]
	}

	if len(fqdn) == 0 {
		fqdn = strings.Join([]string{namespace, atype, alias}, ".")
	}

	for _, plugin := range ctx.StringSlice("plugin") {
		// registry=etcd:broker=nats
		for _, p := range strings.Split(plugin, ":") {
			// registry=etcd
			parts := strings.Split(p, "=")
			if len(parts) < 2 {
				continue
			}
			plugins = append(plugins, path.Join(parts...))
		}
	}

	var c config

	switch atype {
	case "function":
		// create service config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainFNC},
				{"generate.go", tmpl.GenerateFile},
				{"plugin.go", tmpl.Plugin},
				{"handler/" + alias + ".go", tmpl.HandlerFNC},
				{"subscriber/" + alias + ".go", tmpl.SubscriberFNC},
				{"proto/" + alias + "/" + alias + ".proto", tmpl.ProtoFNC},
				{"Dockerfile", tmpl.DockerFNC},
				{"Makefile", tmpl.Makefile},
				{"README.md", tmpl.ReadmeFNC},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: protoComments(goDir, alias),
		}
	case "service":
		// create service config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainSRV},
				{"generate.go", tmpl.GenerateFile},
				{"plugin.go", tmpl.Plugin},
				{"handler/" + alias + ".go", tmpl.HandlerSRV},
				{"subscriber/" + alias + ".go", tmpl.SubscriberSRV},
				{"proto/" + alias + "/" + alias + ".proto", tmpl.ProtoSRV},
				{"Dockerfile", tmpl.DockerSRV},
				{"Makefile", tmpl.Makefile},
				{"README.md", tmpl.Readme},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: protoComments(goDir, alias),
		}
	case "api":
		// create api config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainAPI},
				{"generate.go", tmpl.GenerateFile},
				{"plugin.go", tmpl.Plugin},
				{"client/" + alias + ".go", tmpl.WrapperAPI},
				{"handler/" + alias + ".go", tmpl.HandlerAPI},
				{"proto/" + alias + "/" + alias + ".proto", tmpl.ProtoAPI},
				{"Makefile", tmpl.Makefile},
				{"Dockerfile", tmpl.DockerSRV},
				{"README.md", tmpl.Readme},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: protoComments(goDir, alias),
		}
	case "web":
		// create service config
		c = config{
			Alias:     alias,
			Command:   command,
			Namespace: namespace,
			Type:      atype,
			FQDN:      fqdn,
			Dir:       dir,
			GoDir:     goDir,
			GoPath:    goPath,
			UseGoPath: useGoPath,
			Plugins:   plugins,
			Files: []file{
				{"main.go", tmpl.MainWEB},
				{"plugin.go", tmpl.Plugin},
				{"handler/handler.go", tmpl.HandlerWEB},
				{"html/index.html", tmpl.HTMLWEB},
				{"Dockerfile", tmpl.DockerWEB},
				{"Makefile", tmpl.Makefile},
				{"README.md", tmpl.Readme},
				{".gitignore", tmpl.GitIgnore},
			},
			Comments: []string{},
		}
	default:
		fmt.Println("Unknown type", atype)
		return
	}

	// set gomodule
	if useGoModule != "off" {
		c.Files = append(c.Files, file{"go.mod", tmpl.Module})
	}

	if err := create(c); err != nil {
		fmt.Println(err)
		return
	}
}

func Commands() []*cli.Command {
	return []*cli.Command{
		{
			Name:  "new",
			Usage: "Create a service template",
			Flags: []cli.Flag{
				&cli.StringFlag{
					Name:  "namespace",
					Usage: "Namespace for the service e.g com.example",
					Value: "go.micro",
				},
				&cli.StringFlag{
					Name:  "type",
					Usage: "Type of service e.g api, function, service, web",
					Value: "service",
				},
				&cli.StringFlag{
					Name:  "fqdn",
					Usage: "FQDN of service e.g com.example.service.service (defaults to namespace.type.alias)",
				},
				&cli.StringFlag{
					Name:  "alias",
					Usage: "Alias is the short name used as part of combined name if specified",
				},
				&cli.StringSliceFlag{
					Name:  "plugin",
					Usage: "Specify plugins e.g --plugin=registry=etcd:broker=nats or use flag multiple times",
				},
				&cli.BoolFlag{
					Name:  "gopath",
					Usage: "Create the service in the gopath.",
				},
			},
			Action: func(c *cli.Context) error {
				run(c)
				return nil
			},
		},
	}
}
<|endoftext|>


<commit_before>package chat

import "regexp"

var reStripName = regexp.MustCompile("[^\\w.-]")

const maxLength = 16

// SanitizeName returns a name with only allowed characters and a reasonable length
func SanitizeName(s string) string {
	s = reStripName.ReplaceAllString(s, "")
	nameLength := maxLength
	if len(s) <= maxLength {
		nameLength = len(s)
	}
	s = s[:nameLength]
	return s
}

var reStripData = regexp.MustCompile("[^[:ascii:]]")

// SanitizeData returns a string with only allowed characters for client-provided metadata inputs.
func SanitizeData(s string) string {
	return reStripData.ReplaceAllString(s, "")
}
<commit_msg>Strip control characters from metadata inputs (#257)<commit_after>package chat

import "regexp"

var reStripName = regexp.MustCompile("[^\\w.-]")

const maxLength = 16

// SanitizeName returns a name with only allowed characters and a reasonable length
func SanitizeName(s string) string {
	s = reStripName.ReplaceAllString(s, "")
	nameLength := maxLength
	if len(s) <= maxLength {
		nameLength = len(s)
	}
	s = s[:nameLength]
	return s
}

var reStripData = regexp.MustCompile("[^[:ascii:]]|[[:cntrl:]]")

// SanitizeData returns a string with only allowed characters for client-provided metadata inputs.
func SanitizeData(s string) string {
	return reStripData.ReplaceAllString(s, "")
}
<|endoftext|>


<commit_before>/* Copyright 2014 Ooyala, Inc. All rights reserved.
 *
 * This file is 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 client

import (
	. "atlantis/manager/rpc/types"
	"atlantis/router/config"
)

type UpdatePoolCommand struct {
	Name             string   `short:"n" long:"name" description:"the name of the pool"`
	HealthCheckEvery string   `short:"e" long:"check-every" default:"5s" description:"how often to check healthz"`
	HealthzTimeout   string   `short:"z" long:"healthz-timeout" default:"5s" description:"timeout for healthz checks"`
	RequestTimeout   string   `short:"r" long:"request-timeout" default:"120s" description:"timeout for requests"`
	Status           string   `short:"s" long:"status" default:"OK" description:"the pool's status"`
	Hosts            []string `short:"H" long:"host" description:"the pool's hosts"`
	Internal         bool     `short:"i" long:"internal" description:"true if internal"`
}

func (c *UpdatePoolCommand) Execute(args []string) error {
	err := Init()
	if err != nil {
		return OutputError(err)
	}
	Log("Update Pool...")
	hosts := make(map[string]config.Host, len(c.Hosts))
	for _, host := range c.Hosts {
		hosts[host] = config.Host{Address: host}
	}
	arg := ManagerUpdatePoolArg{dummyAuthArg, config.Pool{Name: c.Name, Hosts: hosts, Internal: c.Internal,
		Config: config.PoolConfig{HealthzEvery: c.HealthCheckEvery, HealthzTimeout: c.HealthzTimeout,
			RequestTimeout: c.RequestTimeout, Status: c.Status}}}
	var reply ManagerUpdatePoolReply
	err = rpcClient.CallAuthed("UpdatePool", &arg, &reply)
	if err != nil {
		return OutputError(err)
	}
	Log("-> status: %s", reply.Status)
	return Output(map[string]interface{}{"status": reply.Status}, nil, nil)
}

type DeletePoolCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the pool"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeletePoolArg
	Reply    ManagerDeletePoolReply
}

type GetPoolCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the pool"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetPoolArg
	Reply    ManagerGetPoolReply
}

type ListPoolsCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListPoolsArg
	Reply    ManagerListPoolsReply
}

type UpdateRuleCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the rule"`
	Type     string `short:"t" long:"type" description:"the type of the rule"`
	Value    string `short:"v" long:"value" description:"the rule's value"`
	Next     string `short:"x" long:"next" description:"the next ruleset"`
	Pool     string `short:"p" long:"pool" description:"the pool to point to if this rule succeeds"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerUpdateRuleArg
	Reply    ManagerUpdateRuleReply
}

type DeleteRuleCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the rule"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeleteRuleArg
	Reply    ManagerDeleteRuleReply
}

type GetRuleCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the rule"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetRuleArg
	Reply    ManagerGetRuleReply
}

type ListRulesCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListRulesArg
	Reply    ManagerListRulesReply
}

type UpdateTrieCommand struct {
	Name     string   `short:"n" long:"name" description:"the name of the rule"`
	Rules    []string `short:"r" long:"rule" description:"the rules that make up the ruleset"`
	Internal bool     `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerUpdateTrieArg
	Reply    ManagerUpdateTrieReply
}

type DeleteTrieCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the trie"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeleteTrieArg
	Reply    ManagerDeleteTrieReply
}

type GetTrieCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the trie"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetTrieArg
	Reply    ManagerGetTrieReply
}

type ListTriesCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListTriesArg
	Reply    ManagerListTriesReply
}

type UpdatePortCommand struct {
	Port     uint16 `short:"p" long:"port" description:"the actual port to listen on"`
	Trie     string `short:"t" long:"trie" description:"the trie to use as root for this port"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerUpdatePortArg
	Reply    ManagerUpdatePortReply
}

type DeletePortCommand struct {
	Port     uint16 `short:"p" long:"port" description:"the port number"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeletePortArg
	Reply    ManagerDeletePortReply
}

type GetPortCommand struct {
	Port     uint16 `short:"p" long:"port" description:"the port number"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetPortArg
	Reply    ManagerGetPortReply
}

type ListPortsCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListPortsArg
	Reply    ManagerListPortsReply
}

type GetAppEnvPortCommand struct {
	App        string `short:"a" long:"app" description:"the app of the port"`
	Env        string `short:"e" long:"env" description:"the env of the port"`
	Internal   bool   `short:"i" long:"internal" description:"true if internal"`
	Properties string `message:"Get AppEnv Port"`
	Arg        ManagerGetAppEnvPortArg
	Reply      ManagerGetAppEnvPortReply
}

type ListAppEnvsWithPortCommand struct {
	Internal   bool   `short:"i" long:"internal" description:"true if internal"`
	Properties string `message:"List AppEnvs With Ports" field:"AppEnvs" name:"app+envs"`
	Arg        ManagerListAppEnvsWithPortArg
	Reply      ManagerListAppEnvsWithPortReply
}
<commit_msg>Client: Add special-case UpdateTrie Executor back; genericExecutor failed there.<commit_after>/* Copyright 2014 Ooyala, Inc. All rights reserved.
 *
 * This file is 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 client

import (
	. "atlantis/manager/rpc/types"
	"atlantis/router/config"
)

type UpdatePoolCommand struct {
	Name             string   `short:"n" long:"name" description:"the name of the pool"`
	HealthCheckEvery string   `short:"e" long:"check-every" default:"5s" description:"how often to check healthz"`
	HealthzTimeout   string   `short:"z" long:"healthz-timeout" default:"5s" description:"timeout for healthz checks"`
	RequestTimeout   string   `short:"r" long:"request-timeout" default:"120s" description:"timeout for requests"`
	Status           string   `short:"s" long:"status" default:"OK" description:"the pool's status"`
	Hosts            []string `short:"H" long:"host" description:"the pool's hosts"`
	Internal         bool     `short:"i" long:"internal" description:"true if internal"`
}

func (c *UpdatePoolCommand) Execute(args []string) error {
	err := Init()
	if err != nil {
		return OutputError(err)
	}
	Log("Update Pool...")
	hosts := make(map[string]config.Host, len(c.Hosts))
	for _, host := range c.Hosts {
		hosts[host] = config.Host{Address: host}
	}
	arg := ManagerUpdatePoolArg{dummyAuthArg, config.Pool{Name: c.Name, Hosts: hosts, Internal: c.Internal,
		Config: config.PoolConfig{HealthzEvery: c.HealthCheckEvery, HealthzTimeout: c.HealthzTimeout,
			RequestTimeout: c.RequestTimeout, Status: c.Status}}}
	var reply ManagerUpdatePoolReply
	err = rpcClient.CallAuthed("UpdatePool", &arg, &reply)
	if err != nil {
		return OutputError(err)
	}
	Log("-> status: %s", reply.Status)
	return Output(map[string]interface{}{"status": reply.Status}, nil, nil)
}

type DeletePoolCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the pool"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeletePoolArg
	Reply    ManagerDeletePoolReply
}

type GetPoolCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the pool"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetPoolArg
	Reply    ManagerGetPoolReply
}

type ListPoolsCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListPoolsArg
	Reply    ManagerListPoolsReply
}

type UpdateRuleCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the rule"`
	Type     string `short:"t" long:"type" description:"the type of the rule"`
	Value    string `short:"v" long:"value" description:"the rule's value"`
	Next     string `short:"x" long:"next" description:"the next ruleset"`
	Pool     string `short:"p" long:"pool" description:"the pool to point to if this rule succeeds"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerUpdateRuleArg
	Reply    ManagerUpdateRuleReply
}

type DeleteRuleCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the rule"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeleteRuleArg
	Reply    ManagerDeleteRuleReply
}

type GetRuleCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the rule"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetRuleArg
	Reply    ManagerGetRuleReply
}

type ListRulesCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListRulesArg
	Reply    ManagerListRulesReply
}

type UpdateTrieCommand struct {
	Name     string   `short:"n" long:"name" description:"the name of the rule"`
	Rules    []string `short:"r" long:"rule" description:"the rules that make up the ruleset"`
	Internal bool     `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerUpdateTrieArg
	Reply    ManagerUpdateTrieReply
}

func (c *UpdateTrieCommand) Execute(args []string) error {
	err := Init()
	if err != nil {
		return OutputError(err)
	}
	Log("Update Trie...")
	arg := ManagerUpdateTrieArg{dummyAuthArg, config.Trie{Name: c.Name, Rules: c.Rules, Internal: c.Internal}}
	var reply ManagerUpdateTrieReply
	err = rpcClient.CallAuthed("UpdateTrie", &arg, &reply)
	if err != nil {
		return OutputError(err)
	}
	Log("-> status: %s", reply.Status)
	return Output(map[string]interface{}{"status": reply.Status}, nil, nil)
}

type DeleteTrieCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the trie"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeleteTrieArg
	Reply    ManagerDeleteTrieReply
}

type GetTrieCommand struct {
	Name     string `short:"n" long:"name" description:"the name of the trie"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetTrieArg
	Reply    ManagerGetTrieReply
}

type ListTriesCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListTriesArg
	Reply    ManagerListTriesReply
}

type UpdatePortCommand struct {
	Port     uint16 `short:"p" long:"port" description:"the actual port to listen on"`
	Trie     string `short:"t" long:"trie" description:"the trie to use as root for this port"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerUpdatePortArg
	Reply    ManagerUpdatePortReply
}

type DeletePortCommand struct {
	Port     uint16 `short:"p" long:"port" description:"the port number"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerDeletePortArg
	Reply    ManagerDeletePortReply
}

type GetPortCommand struct {
	Port     uint16 `short:"p" long:"port" description:"the port number"`
	Internal bool   `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerGetPortArg
	Reply    ManagerGetPortReply
}

type ListPortsCommand struct {
	Internal bool `short:"i" long:"internal" description:"true if internal"`
	Arg      ManagerListPortsArg
	Reply    ManagerListPortsReply
}

type GetAppEnvPortCommand struct {
	App        string `short:"a" long:"app" description:"the app of the port"`
	Env        string `short:"e" long:"env" description:"the env of the port"`
	Internal   bool   `short:"i" long:"internal" description:"true if internal"`
	Properties string `message:"Get AppEnv Port"`
	Arg        ManagerGetAppEnvPortArg
	Reply      ManagerGetAppEnvPortReply
}

type ListAppEnvsWithPortCommand struct {
	Internal   bool   `short:"i" long:"internal" description:"true if internal"`
	Properties string `message:"List AppEnvs With Ports" field:"AppEnvs" name:"app+envs"`
	Arg        ManagerListAppEnvsWithPortArg
	Reply      ManagerListAppEnvsWithPortReply
}
<|endoftext|>


<commit_before>package chyle

import (
	"github.com/antham/chyle/chyle/config"
	"github.com/antham/chyle/chyle/decorators"
	"github.com/antham/chyle/chyle/extractors"
	"github.com/antham/chyle/chyle/matchers"
	"github.com/antham/chyle/chyle/senders"

	"srcd.works/go-git.v4/plumbing/object"
)

// process represents all configuration operations defined
// needed to create a changelog
type process struct {
	matchers   *[]matchers.Matcher
	extractors *[]extractors.Extracter
	decorators *map[string][]decorators.Decorater
	senders    *[]senders.Sender
}

// newProcess creates process entity from defined configuration
func newProcess(conf *config.CHYLE) *process {
	return &process{
		matchers.Create(conf.FEATURES.MATCHERS, conf.MATCHERS),
		extractors.Create(conf.FEATURES.EXTRACTORS, conf.EXTRACTORS),
		decorators.Create(conf.FEATURES.DECORATORS, conf.DECORATORS),
		senders.Create(conf.FEATURES.SENDERS, conf.SENDERS),
	}
}

// proceed extracts datas from a set of commits
func proceed(process *process, commits *[]object.Commit) error {
	changelog, err := decorators.Decorate(process.decorators,
		extractors.Extract(process.extractors,
			matchers.Filter(process.matchers, commits)))

	if err != nil {
		return err
	}

	return senders.Send(process.senders, changelog)
}
<commit_msg>doc(chyle/process) : rewrite comment<commit_after>package chyle

import (
	"github.com/antham/chyle/chyle/config"
	"github.com/antham/chyle/chyle/decorators"
	"github.com/antham/chyle/chyle/extractors"
	"github.com/antham/chyle/chyle/matchers"
	"github.com/antham/chyle/chyle/senders"

	"srcd.works/go-git.v4/plumbing/object"
)

// process represents all steps executed
// when creating a changelog
type process struct {
	matchers   *[]matchers.Matcher
	extractors *[]extractors.Extracter
	decorators *map[string][]decorators.Decorater
	senders    *[]senders.Sender
}

// newProcess creates process entity from defined configuration
func newProcess(conf *config.CHYLE) *process {
	return &process{
		matchers.Create(conf.FEATURES.MATCHERS, conf.MATCHERS),
		extractors.Create(conf.FEATURES.EXTRACTORS, conf.EXTRACTORS),
		decorators.Create(conf.FEATURES.DECORATORS, conf.DECORATORS),
		senders.Create(conf.FEATURES.SENDERS, conf.SENDERS),
	}
}

// proceed extracts datas from a set of commits
func proceed(process *process, commits *[]object.Commit) error {
	changelog, err := decorators.Decorate(process.decorators,
		extractors.Extract(process.extractors,
			matchers.Filter(process.matchers, commits)))

	if err != nil {
		return err
	}

	return senders.Send(process.senders, changelog)
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 AFP Authors
// This source code is released under the terms of the
// MIT license. Please see the file LICENSE for license details.

package util

import (
	"afp"
	)

func GetTriangleOscillator(samplerate, freq, amp float32) (func() float32) {
	period := samplerate / freq //Roughly, period in slices
	delta := 4 * amp / period
	var val float32 = 0

	return func() float32 {
		ret := val

		val += delta

		if val >= amp || val <= -amp {
			delta = -delta
		}

		return ret
	}
}

func GetSawtootheOscillator(samplerate, freq, amp float32) (func() float32) {
	period := samplerate / freq //Roughly, period in slices
	delta := 2 * amp / period
	var val float32 = 0

	return func() float32 {
		ret := val

		val += delta

		if val >= amp {
			val = -amp
		}

		return ret
	}
}

<commit_msg>Add square oscillator<commit_after>// Copyright (c) 2010 AFP Authors
// This source code is released under the terms of the
// MIT license. Please see the file LICENSE for license details.

package util

import (
	"afp"
	)

func GetTriangleOscillator(samplerate, freq, amp float32) (func() float32) {
	period := samplerate / freq //Roughly, period in slices
	delta := 4 * amp / period
	var val float32 = 0

	return func() float32 {
		ret := val

		val += delta

		if val >= amp || val <= -amp {
			delta = -delta
		}

		return ret
	}
}

func GetSawtootheOscillator(samplerate, freq, amp float32) (func() float32) {
	period := samplerate / freq //Roughly, period in slices
	delta := 2 * amp / period
	var val float32 = 0

	return func() float32 {
		ret := val

		val += delta

		if val >= amp {
			val = -amp
		}

		return ret
	}
}

func GetSquareOscillator(samplerate, freq, amp float32) (func() float32) {
	halfperiod := int(samplerate / (2 * freq)) //Roughly, period in slices
	var val float32 = amp
	var i := 0

	return func() float32 {
		ret := val

		if i++; i >= halfperiod {
			i = 0
			val = -val
		}

		return ret
	}
}

<|endoftext|>


<commit_before>package telebot

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

// Option is a shortcut flag type for certain message features
// (so-called options). It means that instead of passing
// fully-fledged SendOptions* to Send(), you can use these
// flags instead.
//
// Supported options are defined as iota-constants.
//
type Option int

const (
	// NoPreview = SendOptions.DisableWebPagePreview
	NoPreview Option = iota

	// Silent = SendOptions.DisableNotification
	Silent

	// ForceReply = ReplyMarkup.ForceReply
	ForceReply

	// OneTimeKeyboard = ReplyMarkup.OneTimeKeyboard
	OneTimeKeyboard

	// RemoveKeyboard = ReplyMarkup.RemoveKeyboard
	RemoveKeyboard
)

// SendOptions has most complete control over in what way the message
// must be sent, providing an API-complete set of custom properties
// and options.
//
// Despite its power, SendOptions is rather inconvenient to use all
// the way through bot logic, so you might want to consider storing
// and re-using it somewhere or be using Option flags instead.
//
type SendOptions struct {
	// If the message is a reply, original message.
	ReplyTo *Message

	// See ReplyMarkup struct definition.
	ReplyMarkup *ReplyMarkup

	// For text messages, disables previews for links in this message.
	DisableWebPagePreview bool

	// Sends the message silently. iOS users will not receive a notification, Android users will receive a notification with no sound.
	DisableNotification bool

	// ParseMode controls how client apps render your message.
	ParseMode ParseMode
}

func (og *SendOptions) copy() *SendOptions {
	cp := *og
	if cp.ReplyMarkup != nil {
		cp.ReplyMarkup = cp.ReplyMarkup.copy()
	}
	return &cp
}

// ReplyMarkup controls two convenient options for bot-user communications
// such as reply keyboard and inline "keyboard" (a grid of buttons as a part
// of the message).
type ReplyMarkup struct {
	// InlineKeyboard is a grid of InlineButtons displayed in the message.
	//
	// Note: DO NOT confuse with ReplyKeyboard and other keyboard properties!
	InlineKeyboard [][]InlineButton `json:"inline_keyboard,omitempty"`

	// ReplyKeyboard is a grid, consisting of keyboard buttons.
	//
	// Note: you don't need to set HideCustomKeyboard field to show custom keyboard.
	ReplyKeyboard [][]ReplyButton `json:"keyboard,omitempty"`

	// ForceReply forces Telegram clients to display
	// a reply interface to the user (act as if the user
	// has selected the bot‘s message and tapped "Reply").
	ForceReply bool `json:"force_reply,omitempty"`

	// Requests clients to resize the keyboard vertically for optimal fit
	// (e.g. make the keyboard smaller if there are just two rows of buttons).
	//
	// Defaults to false, in which case the custom keyboard is always of the
	// same height as the app's standard keyboard.
	ResizeKeyboard bool `json:"resize_keyboard,omitempty"`

	// Requests clients to hide the reply keyboard as soon as it's been used.
	//
	// Defaults to false.
	OneTimeKeyboard bool `json:"one_time_keyboard,omitempty"`

	// Requests clients to remove the reply keyboard.
	//
	// Defaults to false.
	RemoveKeyboard bool `json:"remove_keyboard,omitempty"`

	// Use this param if you want to force reply from
	// specific users only.
	//
	// Targets:
	// 1) Users that are @mentioned in the text of the Message object;
	// 2) If the bot's message is a reply (has SendOptions.ReplyTo),
	//       sender of the original message.
	Selective bool `json:"selective,omitempty"`
}

func (r *ReplyMarkup) copy() *ReplyMarkup {
	cp := *r

	if len(r.ReplyKeyboard) > 0 {
		cp.ReplyKeyboard = make([][]ReplyButton, len(r.ReplyKeyboard))
		for i, row := range r.ReplyKeyboard {
			cp.ReplyKeyboard[i] = make([]ReplyButton, len(row))
			copy(cp.ReplyKeyboard[i], row)
		}
	}

	if len(r.InlineKeyboard) > 0 {
		cp.InlineKeyboard = make([][]InlineButton, len(r.InlineKeyboard))
		for i, row := range r.InlineKeyboard {
			cp.InlineKeyboard[i] = make([]InlineButton, len(row))
			copy(cp.InlineKeyboard[i], row)
		}
	}

	return &cp
}

// ReplyButton represents a button displayed in reply-keyboard.
//
// Set either Contact or Location to true in order to request
// sensitive info, such as user's phone number or current location.
//
type ReplyButton struct {
	Text string `json:"text"`

	Contact  bool     `json:"request_contact,omitempty"`
	Location bool     `json:"request_location,omitempty"`
	Poll     PollType `json:"request_poll,omitempty"`
}

// InlineKeyboardMarkup represents an inline keyboard that appears
// right next to the message it belongs to.
type InlineKeyboardMarkup struct {
	// Array of button rows, each represented by
	// an Array of KeyboardButton objects.
	InlineKeyboard [][]InlineButton `json:"inline_keyboard,omitempty"`
}

// MarshalJSON implements json.Marshaler. It allows to pass
// PollType as keyboard's poll type instead of KeyboardButtonPollType object.
func (pt PollType) MarshalJSON() ([]byte, error) {
	var aux = struct {
		Type string `json:"type"`
	}{
		Type: string(pt),
	}
	return json.Marshal(&aux)
}

// Row represents an array of buttons, a row
type Row []Btn

// Row create a row of buttons
func (r *ReplyMarkup) Row(many ...Btn) Row {
	return many
}

func (r *ReplyMarkup) Inline(rows ...Row) {
	inlineKeys := make([][]InlineButton, 0, len(rows))
	for i, row := range rows {
		keys := make([]InlineButton, 0, len(row))
		for j, btn := range row {
			btn := btn.Inline()
			if btn == nil {
				panic(fmt.Sprintf(
					"telebot: button row %d column %d is not an inline button",
					i, j))
			}
			keys = append(keys, *btn)
		}
		inlineKeys = append(inlineKeys, keys)
	}

	r.InlineKeyboard = inlineKeys
}

func (r *ReplyMarkup) Reply(rows ...Row) {
	replyKeys := make([][]ReplyButton, 0, len(rows))
	for i, row := range rows {
		keys := make([]ReplyButton, 0, len(row))
		for j, btn := range row {
			btn := btn.Reply()
			if btn == nil {
				panic(fmt.Sprintf(
					"telebot: button row %d column %d is not a reply button",
					i, j))
			}
			keys = append(keys, *btn)
		}
		replyKeys = append(replyKeys, keys)
	}

	r.ReplyKeyboard = replyKeys
}

func (r *ReplyMarkup) Text(text string) Btn {
	return Btn{Text: text}
}

func (r *ReplyMarkup) Contact(text string) Btn {
	return Btn{Contact: true, Text: text}
}

func (r *ReplyMarkup) Location(text string) Btn {
	return Btn{Location: true, Text: text}
}

func (r *ReplyMarkup) Poll(text string, poll PollType) Btn {
	return Btn{Poll: poll, Text: text}
}

func (r *ReplyMarkup) Data(text, unique string, data ...string) Btn {
	return Btn{
		Unique: unique,
		Text:   text,
		Data:   strings.Join(data, "|"),
	}
}

func (r *ReplyMarkup) URL(text, url string) Btn {
	return Btn{Text: text, URL: url}
}

func (r *ReplyMarkup) Query(text, query string) Btn {
	return Btn{Text: text, InlineQuery: query}
}

func (r *ReplyMarkup) QueryChat(text, query string) Btn {
	return Btn{Text: text, InlineQueryChat: query}
}

func (r *ReplyMarkup) Login(text string, login *Login) Btn {
	return Btn{Login: login, Text: text}
}

// Btn is a constructor button, which will later become either a reply, or an inline button.
type Btn struct {
	Unique          string   `json:"unique,omitempty"`
	Text            string   `json:"text,omitempty"`
	URL             string   `json:"url,omitempty"`
	Data            string   `json:"callback_data,omitempty"`
	InlineQuery     string   `json:"switch_inline_query,omitempty"`
	InlineQueryChat string   `json:"switch_inline_query_current_chat,omitempty"`
	Contact         bool     `json:"request_contact,omitempty"`
	Location        bool     `json:"request_location,omitempty"`
	Poll            PollType `json:"request_poll,omitempty"`
	Login           *Login   `json:"login_url,omitempty"`
}

func (b Btn) Inline() *InlineButton {
	return &InlineButton{
		Unique:          b.Unique,
		Text:            b.Text,
		URL:             b.URL,
		Data:            b.Data,
		InlineQuery:     b.InlineQuery,
		InlineQueryChat: b.InlineQueryChat,
		Login:           b.Login,
	}
}

func (b Btn) Reply() *ReplyButton {
	if b.Unique != "" {
		return nil
	}

	return &ReplyButton{
		Text:     b.Text,
		Contact:  b.Contact,
		Location: b.Location,
		Poll:     b.Poll,
	}
}
<commit_msg>options: implement markup Split<commit_after>package telebot

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

// Option is a shortcut flag type for certain message features
// (so-called options). It means that instead of passing
// fully-fledged SendOptions* to Send(), you can use these
// flags instead.
//
// Supported options are defined as iota-constants.
//
type Option int

const (
	// NoPreview = SendOptions.DisableWebPagePreview
	NoPreview Option = iota

	// Silent = SendOptions.DisableNotification
	Silent

	// ForceReply = ReplyMarkup.ForceReply
	ForceReply

	// OneTimeKeyboard = ReplyMarkup.OneTimeKeyboard
	OneTimeKeyboard

	// RemoveKeyboard = ReplyMarkup.RemoveKeyboard
	RemoveKeyboard
)

// SendOptions has most complete control over in what way the message
// must be sent, providing an API-complete set of custom properties
// and options.
//
// Despite its power, SendOptions is rather inconvenient to use all
// the way through bot logic, so you might want to consider storing
// and re-using it somewhere or be using Option flags instead.
//
type SendOptions struct {
	// If the message is a reply, original message.
	ReplyTo *Message

	// See ReplyMarkup struct definition.
	ReplyMarkup *ReplyMarkup

	// For text messages, disables previews for links in this message.
	DisableWebPagePreview bool

	// Sends the message silently. iOS users will not receive a notification, Android users will receive a notification with no sound.
	DisableNotification bool

	// ParseMode controls how client apps render your message.
	ParseMode ParseMode
}

func (og *SendOptions) copy() *SendOptions {
	cp := *og
	if cp.ReplyMarkup != nil {
		cp.ReplyMarkup = cp.ReplyMarkup.copy()
	}
	return &cp
}

// ReplyMarkup controls two convenient options for bot-user communications
// such as reply keyboard and inline "keyboard" (a grid of buttons as a part
// of the message).
type ReplyMarkup struct {
	// InlineKeyboard is a grid of InlineButtons displayed in the message.
	//
	// Note: DO NOT confuse with ReplyKeyboard and other keyboard properties!
	InlineKeyboard [][]InlineButton `json:"inline_keyboard,omitempty"`

	// ReplyKeyboard is a grid, consisting of keyboard buttons.
	//
	// Note: you don't need to set HideCustomKeyboard field to show custom keyboard.
	ReplyKeyboard [][]ReplyButton `json:"keyboard,omitempty"`

	// ForceReply forces Telegram clients to display
	// a reply interface to the user (act as if the user
	// has selected the bot‘s message and tapped "Reply").
	ForceReply bool `json:"force_reply,omitempty"`

	// Requests clients to resize the keyboard vertically for optimal fit
	// (e.g. make the keyboard smaller if there are just two rows of buttons).
	//
	// Defaults to false, in which case the custom keyboard is always of the
	// same height as the app's standard keyboard.
	ResizeKeyboard bool `json:"resize_keyboard,omitempty"`

	// Requests clients to hide the reply keyboard as soon as it's been used.
	//
	// Defaults to false.
	OneTimeKeyboard bool `json:"one_time_keyboard,omitempty"`

	// Requests clients to remove the reply keyboard.
	//
	// Defaults to false.
	RemoveKeyboard bool `json:"remove_keyboard,omitempty"`

	// Use this param if you want to force reply from
	// specific users only.
	//
	// Targets:
	// 1) Users that are @mentioned in the text of the Message object;
	// 2) If the bot's message is a reply (has SendOptions.ReplyTo),
	//       sender of the original message.
	Selective bool `json:"selective,omitempty"`
}

func (r *ReplyMarkup) copy() *ReplyMarkup {
	cp := *r

	if len(r.ReplyKeyboard) > 0 {
		cp.ReplyKeyboard = make([][]ReplyButton, len(r.ReplyKeyboard))
		for i, row := range r.ReplyKeyboard {
			cp.ReplyKeyboard[i] = make([]ReplyButton, len(row))
			copy(cp.ReplyKeyboard[i], row)
		}
	}

	if len(r.InlineKeyboard) > 0 {
		cp.InlineKeyboard = make([][]InlineButton, len(r.InlineKeyboard))
		for i, row := range r.InlineKeyboard {
			cp.InlineKeyboard[i] = make([]InlineButton, len(row))
			copy(cp.InlineKeyboard[i], row)
		}
	}

	return &cp
}

// ReplyButton represents a button displayed in reply-keyboard.
//
// Set either Contact or Location to true in order to request
// sensitive info, such as user's phone number or current location.
//
type ReplyButton struct {
	Text string `json:"text"`

	Contact  bool     `json:"request_contact,omitempty"`
	Location bool     `json:"request_location,omitempty"`
	Poll     PollType `json:"request_poll,omitempty"`
}

// InlineKeyboardMarkup represents an inline keyboard that appears
// right next to the message it belongs to.
type InlineKeyboardMarkup struct {
	// Array of button rows, each represented by
	// an Array of KeyboardButton objects.
	InlineKeyboard [][]InlineButton `json:"inline_keyboard,omitempty"`
}

// MarshalJSON implements json.Marshaler. It allows to pass
// PollType as keyboard's poll type instead of KeyboardButtonPollType object.
func (pt PollType) MarshalJSON() ([]byte, error) {
	var aux = struct {
		Type string `json:"type"`
	}{
		Type: string(pt),
	}
	return json.Marshal(&aux)
}

// Row represents an array of buttons, a row.
type Row []Btn

// Row creates a row of buttons.
func (r *ReplyMarkup) Row(many ...Btn) Row {
	return many
}

// Split splits the keyboard into the rows with N maximum number of buttons.
// For example, if you pass six buttons and 3 as the max, you get two rows with
// three buttons in each.
//
// Split(3, six buttons...) -> [[1, 2, 3], [4, 5, 6]]
// Split(2, six buttons...) -> [[1, 2],[3, 4],[5, 6]]
//
func (r *ReplyMarkup) Split(max int, bs ...Btn) []Row {
	rows := make([]Row, (1+len(bs))/max)
	for i, b := range bs {
		i /= max
		rows[i] = append(rows[i], b)
	}
	return rows
}

func (r *ReplyMarkup) Inline(rows ...Row) {
	inlineKeys := make([][]InlineButton, 0, len(rows))
	for i, row := range rows {
		keys := make([]InlineButton, 0, len(row))
		for j, btn := range row {
			btn := btn.Inline()
			if btn == nil {
				panic(fmt.Sprintf(
					"telebot: button row %d column %d is not an inline button",
					i, j))
			}
			keys = append(keys, *btn)
		}
		inlineKeys = append(inlineKeys, keys)
	}

	r.InlineKeyboard = inlineKeys
}

func (r *ReplyMarkup) Reply(rows ...Row) {
	replyKeys := make([][]ReplyButton, 0, len(rows))
	for i, row := range rows {
		keys := make([]ReplyButton, 0, len(row))
		for j, btn := range row {
			btn := btn.Reply()
			if btn == nil {
				panic(fmt.Sprintf(
					"telebot: button row %d column %d is not a reply button",
					i, j))
			}
			keys = append(keys, *btn)
		}
		replyKeys = append(replyKeys, keys)
	}

	r.ReplyKeyboard = replyKeys
}

func (r *ReplyMarkup) Text(text string) Btn {
	return Btn{Text: text}
}

func (r *ReplyMarkup) Contact(text string) Btn {
	return Btn{Contact: true, Text: text}
}

func (r *ReplyMarkup) Location(text string) Btn {
	return Btn{Location: true, Text: text}
}

func (r *ReplyMarkup) Poll(text string, poll PollType) Btn {
	return Btn{Poll: poll, Text: text}
}

func (r *ReplyMarkup) Data(text, unique string, data ...string) Btn {
	return Btn{
		Unique: unique,
		Text:   text,
		Data:   strings.Join(data, "|"),
	}
}

func (r *ReplyMarkup) URL(text, url string) Btn {
	return Btn{Text: text, URL: url}
}

func (r *ReplyMarkup) Query(text, query string) Btn {
	return Btn{Text: text, InlineQuery: query}
}

func (r *ReplyMarkup) QueryChat(text, query string) Btn {
	return Btn{Text: text, InlineQueryChat: query}
}

func (r *ReplyMarkup) Login(text string, login *Login) Btn {
	return Btn{Login: login, Text: text}
}

// Btn is a constructor button, which will later become either a reply, or an inline button.
type Btn struct {
	Unique          string   `json:"unique,omitempty"`
	Text            string   `json:"text,omitempty"`
	URL             string   `json:"url,omitempty"`
	Data            string   `json:"callback_data,omitempty"`
	InlineQuery     string   `json:"switch_inline_query,omitempty"`
	InlineQueryChat string   `json:"switch_inline_query_current_chat,omitempty"`
	Contact         bool     `json:"request_contact,omitempty"`
	Location        bool     `json:"request_location,omitempty"`
	Poll            PollType `json:"request_poll,omitempty"`
	Login           *Login   `json:"login_url,omitempty"`
}

func (b Btn) Inline() *InlineButton {
	return &InlineButton{
		Unique:          b.Unique,
		Text:            b.Text,
		URL:             b.URL,
		Data:            b.Data,
		InlineQuery:     b.InlineQuery,
		InlineQueryChat: b.InlineQueryChat,
		Login:           b.Login,
	}
}

func (b Btn) Reply() *ReplyButton {
	if b.Unique != "" {
		return nil
	}

	return &ReplyButton{
		Text:     b.Text,
		Contact:  b.Contact,
		Location: b.Location,
		Poll:     b.Poll,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"gotest.tools/assert"
	"io/ioutil"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/client-go/tools/cache"
	"knative.dev/serving/pkg/apis/serving/v1alpha1"
	servingClientSet "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1"
	"net/http"
	"regexp"
	"testing"
	"time"
)

/*
These tests assume that there is a Kubernetes cluster running and that Knative
has been deployed. "utils/setup.sh" can be used to do that.
*/
const namespace string = "default"
const clusterURL string = "http://localhost:8080"
const domain string = "example.com"

var kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")

func TestSimpleScenario(t *testing.T) {
	servingClient, err := KnativeServingClient(*kubeconfig)
	if err != nil {
		t.Fatal(err)
	}

	service, err := setupSimpleScenario(servingClient)
	if err != nil {
		t.Fatal(err)
	}

	// Prepare the request
	client := &http.Client{}
	req, err := http.NewRequest("GET", clusterURL, nil)
	if err != nil {
		t.Fatal(err)
	}
	req.Host = fmt.Sprintf("%s.%s.%s", service.Name, namespace, domain)

	// Do the request
	resp, err := client.Do(req)
	if err != nil {
		t.Fatal(err)
	}
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	// The "hello world" service just returns "Hello World!"
	assert.Equal(t, string(respBody), "Hello World!\n")

	err = cleanSimpleScenario(servingClient, service.Name)
	if err != nil {
		t.Fatal(err)
	}
}

// Deploys a simple "Hello World" serving and returns it.
func setupSimpleScenario(servingClient *servingClientSet.ServingV1alpha1Client) (*v1alpha1.Service, error) {
	service := ExampleHelloWorldServing()

	// Make sure there's nothing left from previous tests
	err := cleanSimpleScenario(servingClient, service.Name)
	if err != nil {
		return nil, err
	}

	eventsServiceReady := make(chan struct{})
	stopChan := make(chan struct{})
	go watchForServiceReady(servingClient, service.Name, eventsServiceReady, stopChan)

	createdService, err := servingClient.Services(namespace).Create(&service)

	if err != nil {
		return nil, err
	}

	// Wait until the service is ready plus some time to make sure that Envoy
	// refreshed the config.
	<-eventsServiceReady
	time.Sleep(5 * time.Second)

	return createdService, nil
}

func watchForServiceReady(servingClient *servingClientSet.ServingV1alpha1Client,
	serviceName string,
	events chan<- struct{},
	stopChan <-chan struct{}) {

	restClient := servingClient.RESTClient()

	watchlist := cache.NewListWatchFromClient(restClient, "services", namespace, fields.Everything())

	_, controller := cache.NewInformer(
		watchlist,
		&v1alpha1.Service{},
		time.Second*1,
		cache.ResourceEventHandlerFuncs{
			AddFunc: func(obj interface{}) {
				service := obj.(*v1alpha1.Service)

				if service.Name == serviceName && service.Status.IsReady() {
					events <- struct{}{}
				}
			},
			UpdateFunc: func(oldObj, newObj interface{}) {
				updatedService := newObj.(*v1alpha1.Service)

				if updatedService.Name == serviceName && updatedService.Status.IsReady() {
					events <- struct{}{}
				}
			},
		},
	)

	controller.Run(stopChan)
}

// Cleans the serving deployed in the simple scenario test.
// If the serving does not exist, it does not return an error, it simply does
// nothing.
func cleanSimpleScenario(servingClient *servingClientSet.ServingV1alpha1Client, serviceName string) error {
	err := servingClient.Services(namespace).Delete(serviceName, &v1.DeleteOptions{})

	if err != nil {
		// If the error is that the serving does not exist, just ignore.
		isNotFoundErr, err := regexp.MatchString(
			err.Error(),
			fmt.Sprintf("\"%s\" not found", serviceName),
		)

		if isNotFoundErr {
			return nil
		} else {
			return err
		}
	}

	return err
}
<commit_msg>Use 127.0.0.1.nip.io for the integration test as domain<commit_after>package main

import (
	"flag"
	"fmt"
	"gotest.tools/assert"
	"io/ioutil"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/client-go/tools/cache"
	"knative.dev/serving/pkg/apis/serving/v1alpha1"
	servingClientSet "knative.dev/serving/pkg/client/clientset/versioned/typed/serving/v1alpha1"
	"net/http"
	"regexp"
	"testing"
	"time"
)

/*
These tests assume that there is a Kubernetes cluster running and that Knative
has been deployed. "utils/setup.sh" can be used to do that.
*/
const namespace string = "default"
const clusterURL string = "http://localhost:8080"
const domain string = "127.0.0.1.nip.io"

var kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")

func TestSimpleScenario(t *testing.T) {
	servingClient, err := KnativeServingClient(*kubeconfig)
	if err != nil {
		t.Fatal(err)
	}

	service, err := setupSimpleScenario(servingClient)
	if err != nil {
		t.Fatal(err)
	}

	// Prepare the request
	client := &http.Client{}
	req, err := http.NewRequest("GET", clusterURL, nil)
	if err != nil {
		t.Fatal(err)
	}
	req.Host = fmt.Sprintf("%s.%s.%s", service.Name, namespace, domain)

	// Do the request
	resp, err := client.Do(req)
	if err != nil {
		t.Fatal(err)
	}
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	// The "hello world" service just returns "Hello World!"
	assert.Equal(t, string(respBody), "Hello World!\n")

	err = cleanSimpleScenario(servingClient, service.Name)
	if err != nil {
		t.Fatal(err)
	}
}

// Deploys a simple "Hello World" serving and returns it.
func setupSimpleScenario(servingClient *servingClientSet.ServingV1alpha1Client) (*v1alpha1.Service, error) {
	service := ExampleHelloWorldServing()

	// Make sure there's nothing left from previous tests
	err := cleanSimpleScenario(servingClient, service.Name)
	if err != nil {
		return nil, err
	}

	eventsServiceReady := make(chan struct{})
	stopChan := make(chan struct{})
	go watchForServiceReady(servingClient, service.Name, eventsServiceReady, stopChan)

	createdService, err := servingClient.Services(namespace).Create(&service)

	if err != nil {
		return nil, err
	}

	// Wait until the service is ready plus some time to make sure that Envoy
	// refreshed the config.
	<-eventsServiceReady
	time.Sleep(5 * time.Second)

	return createdService, nil
}

func watchForServiceReady(servingClient *servingClientSet.ServingV1alpha1Client,
	serviceName string,
	events chan<- struct{},
	stopChan <-chan struct{}) {

	restClient := servingClient.RESTClient()

	watchlist := cache.NewListWatchFromClient(restClient, "services", namespace, fields.Everything())

	_, controller := cache.NewInformer(
		watchlist,
		&v1alpha1.Service{},
		time.Second*1,
		cache.ResourceEventHandlerFuncs{
			AddFunc: func(obj interface{}) {
				service := obj.(*v1alpha1.Service)

				if service.Name == serviceName && service.Status.IsReady() {
					events <- struct{}{}
				}
			},
			UpdateFunc: func(oldObj, newObj interface{}) {
				updatedService := newObj.(*v1alpha1.Service)

				if updatedService.Name == serviceName && updatedService.Status.IsReady() {
					events <- struct{}{}
				}
			},
		},
	)

	controller.Run(stopChan)
}

// Cleans the serving deployed in the simple scenario test.
// If the serving does not exist, it does not return an error, it simply does
// nothing.
func cleanSimpleScenario(servingClient *servingClientSet.ServingV1alpha1Client, serviceName string) error {
	err := servingClient.Services(namespace).Delete(serviceName, &v1.DeleteOptions{})

	if err != nil {
		// If the error is that the serving does not exist, just ignore.
		isNotFoundErr, err := regexp.MatchString(
			err.Error(),
			fmt.Sprintf("\"%s\" not found", serviceName),
		)

		if isNotFoundErr {
			return nil
		} else {
			return err
		}
	}

	return err
}
<|endoftext|>


<commit_before>//
// file: ./clean.go
// desc: binary for remove os generated files
// author:
// legal:
//
package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var (
	all = flag.Bool("all", false, "which include subdirectory")
)

func main() {
	flag.Parse()

	if len(flag.Args()) == 0 {
    log.Print("./")
		clean("./")
	} else {
		for _, args := range flag.Args()[1:] {
      log.Print(args)
			clean(args)
		}
	}

}

func clean(dir string) {
	files, _ := ioutil.ReadDir(dir)
	for _, f := range files {
		if !f.IsDir() && hasPattern(f.Name()) {
			err := os.Remove(filepath.Clean(dir + "/" + f.Name()))
			if err != nil {
				log.Print(err)
			} else {
				log.Println("Remove", filepath.Clean(dir+"/"+f.Name()))
			}
		} else if !f.IsDir() && !hasPattern(f.Name()) {
			continue
		} else {
			if *all {
				clean(filepath.Clean(dir + "/" + f.Name()))
			}
		}
	}
}

func hasPattern(name string) bool {
	patterns := []string{
		".DS_Store",
		".DS_Store?",
		"._*",
		".Spotlight-V100",
		".Trashes",
		"ehthumbs.db",
		"Thumbs.db",
	}

	for _, pattern := range patterns {
		if strings.Contains(name, pattern) {
			return true
		}
	}
	return false
}
<commit_msg>Remove log.<commit_after>//
// file: ./clean.go
// desc: binary for remove os generated files
// author:
// legal:
//
package main

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var (
	all = flag.Bool("all", false, "which include subdirectory")
)

func main() {
	flag.Parse()

	if len(flag.Args()) == 0 {
		clean("./")
	} else {
		for _, args := range flag.Args()[1:] {
			clean(args)
		}
	}

}

func clean(dir string) {
	files, _ := ioutil.ReadDir(dir)
	for _, f := range files {
		if !f.IsDir() && hasPattern(f.Name()) {
			err := os.Remove(filepath.Clean(dir + "/" + f.Name()))
			if err != nil {
				log.Print(err)
			} else {
				log.Println("Remove", filepath.Clean(dir+"/"+f.Name()))
			}
		} else if !f.IsDir() && !hasPattern(f.Name()) {
			continue
		} else {
			if *all {
				clean(filepath.Clean(dir + "/" + f.Name()))
			}
		}
	}
}

func hasPattern(name string) bool {
	patterns := []string{
		".DS_Store",
		".DS_Store?",
		"._*",
		".Spotlight-V100",
		".Trashes",
		"ehthumbs.db",
		"Thumbs.db",
	}

	for _, pattern := range patterns {
		if strings.Contains(name, pattern) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// Copyright 2015, Timothy Bogdala <tdb@animal-machine.com>
// See the LICENSE file for more details.

package fizzle

import (
	"math"

	mgl "github.com/go-gl/mathgl/mgl32"
)

var (
	upVector   = mgl.Vec3{0.0, 1.0, 0.0}
	sideVector = mgl.Vec3{1.0, 0.0, 0.0}
)

// Camera keeps track of the view rotation and position and provides
// utility methods to generate a view matrix.
//
// The default mode of the camera is to provide a free-moving camera
// that is adjusted by yaw and pitch.
type Camera struct {
	// store the pitch and yaw as angles to convert into
	// quaternions on change. this allows for movement directed
	// by yaw, but not affected by pitch.
	// NOTE: specified in radians.
	yaw   float32
	pitch float32

	// derived from camYaw and camPitch and is what is used for the camera
	rotation mgl.Quat
	position mgl.Vec3
}

// NewCamera will create a new camera at a given position with no rotations applied.
func NewCamera(eyePosition mgl.Vec3) *Camera {
	const yaw float32 = 0.0

	cam := new(Camera)
	cam.position = eyePosition
	cam.rotation = mgl.QuatRotate(yaw, mgl.Vec3{0.0, 1.0, 0.0})
	return cam
}

// GetViewMatrix returns a 4x4 matrix for the view rot/trans/scale.
func (c *Camera) GetViewMatrix() mgl.Mat4 {
	view := c.rotation.Mat4()
	view = view.Mul4(mgl.Translate3D(-c.position[0], -c.position[1], -c.position[2]))
	return view
}

// GetPosition returns the eye position of the camera
func (c *Camera) GetPosition() mgl.Vec3 {
	return c.position
}

// UpdatePosition adds delta values to the eye position vector.
func (c *Camera) UpdatePosition(dX, dY, dZ float32) {
	c.position[0] += dX
	c.position[1] += dY
	c.position[2] += dZ
}

// SetYawAndPitch sets the yaw and pitch radians directly for the camera
func (c *Camera) SetYawAndPitch(yaw, pitch float32) {
	c.yaw = yaw
	c.pitch = pitch
	c.generateRotation()
}

// UpdateYaw adds a delta to the camera yaw and regenerates the rotation quaternion.
func (c *Camera) UpdateYaw(delta float32) {
	c.yaw += delta
	c.generateRotation()
}

// GetYaw returns the yaw of the camera in radians
func (c *Camera) GetYaw() float32 {
	return c.yaw
}

// GetPitch returns the pitch of the camera in radians
func (c *Camera) GetPitch() float32 {
	return c.pitch
}

// UpdatePitch adds a delta to the camera pitch and regenerates the rotation quaternion.
func (c *Camera) UpdatePitch(delta float32) {
	c.pitch += delta
	c.generateRotation()
}

// LookAtDirect calculates a view rotation using the current Camera
// position so that it will look at the target coordinate.
// Uses standard up axis of {0,1,0}.
var (
	defaultLookAtUp = mgl.Vec3{0.0, 1.0, 0.0}
)

func (c *Camera) LookAtDirect(target mgl.Vec3) {
	c.rotation = mgl.QuatLookAtV(c.position, target, defaultLookAtUp)
}

// LookAt adjusts the position of the camera based on the camera yaw/pitch
// and the target location passed in. It does automatically adjust
// the camera's internal rotation quaternion.
func (c *Camera) LookAt(target mgl.Vec3, distance float32) {
	// use trig to get the camera position scaled by distance
	rotatedX := float32(math.Cos(float64(c.yaw))) * distance
	rotatedZ := float32(math.Sin(float64(c.yaw))) * distance

	// set the camera's location
	c.position[0] = target[0] + rotatedX
	c.position[1] = target[1] + distance
	c.position[2] = target[2] + rotatedZ

	correctedYaw := float32(math.Atan2(float64(c.position[0]-target[0]), float64(c.position[2]-target[2])))

	// update the rotation quaternion
	camYawQ := mgl.QuatRotate(-1*correctedYaw, upVector)
	camPitchQ := mgl.QuatRotate(c.pitch, sideVector)
	c.rotation = camPitchQ.Mul(camYawQ)
}

// generateRotation recalculates the rotation quaternion based on the pitch and yaw radians.
func (c *Camera) generateRotation() {
	camYawQ := mgl.QuatRotate(c.yaw, upVector)
	camPitchQ := mgl.QuatRotate(c.pitch, sideVector)
	c.rotation = camPitchQ.Mul(camYawQ)
}
<commit_msg>added an absolute setposition to camera<commit_after>// Copyright 2015, Timothy Bogdala <tdb@animal-machine.com>
// See the LICENSE file for more details.

package fizzle

import (
	"math"

	mgl "github.com/go-gl/mathgl/mgl32"
)

var (
	upVector   = mgl.Vec3{0.0, 1.0, 0.0}
	sideVector = mgl.Vec3{1.0, 0.0, 0.0}
)

// Camera keeps track of the view rotation and position and provides
// utility methods to generate a view matrix.
//
// The default mode of the camera is to provide a free-moving camera
// that is adjusted by yaw and pitch.
type Camera struct {
	// store the pitch and yaw as angles to convert into
	// quaternions on change. this allows for movement directed
	// by yaw, but not affected by pitch.
	// NOTE: specified in radians.
	yaw   float32
	pitch float32

	// derived from camYaw and camPitch and is what is used for the camera
	rotation mgl.Quat
	position mgl.Vec3
}

// NewCamera will create a new camera at a given position with no rotations applied.
func NewCamera(eyePosition mgl.Vec3) *Camera {
	const yaw float32 = 0.0

	cam := new(Camera)
	cam.position = eyePosition
	cam.rotation = mgl.QuatRotate(yaw, mgl.Vec3{0.0, 1.0, 0.0})
	return cam
}

// GetViewMatrix returns a 4x4 matrix for the view rot/trans/scale.
func (c *Camera) GetViewMatrix() mgl.Mat4 {
	view := c.rotation.Mat4()
	view = view.Mul4(mgl.Translate3D(-c.position[0], -c.position[1], -c.position[2]))
	return view
}

// GetPosition returns the eye position of the camera
func (c *Camera) GetPosition() mgl.Vec3 {
	return c.position
}

// UpdatePosition adds delta values to the eye position vector.
func (c *Camera) UpdatePosition(dX, dY, dZ float32) {
	c.position[0] += dX
	c.position[1] += dY
	c.position[2] += dZ
}

// SetPosition sets the position of the camera with an absolute coordinate.
func (c *Camera) SetPosition(x, y, z float32) {
	c.position[0] = x
	c.position[1] = y
	c.position[2] = z
}

// SetYawAndPitch sets the yaw and pitch radians directly for the camera
func (c *Camera) SetYawAndPitch(yaw, pitch float32) {
	c.yaw = yaw
	c.pitch = pitch
	c.generateRotation()
}

// UpdateYaw adds a delta to the camera yaw and regenerates the rotation quaternion.
func (c *Camera) UpdateYaw(delta float32) {
	c.yaw += delta
	c.generateRotation()
}

// GetYaw returns the yaw of the camera in radians
func (c *Camera) GetYaw() float32 {
	return c.yaw
}

// GetPitch returns the pitch of the camera in radians
func (c *Camera) GetPitch() float32 {
	return c.pitch
}

// UpdatePitch adds a delta to the camera pitch and regenerates the rotation quaternion.
func (c *Camera) UpdatePitch(delta float32) {
	c.pitch += delta
	c.generateRotation()
}

// LookAtDirect calculates a view rotation using the current Camera
// position so that it will look at the target coordinate.
// Uses standard up axis of {0,1,0}.
var (
	defaultLookAtUp = mgl.Vec3{0.0, 1.0, 0.0}
)

func (c *Camera) LookAtDirect(target mgl.Vec3) {
	c.rotation = mgl.QuatLookAtV(c.position, target, defaultLookAtUp)
}

// LookAt adjusts the position of the camera based on the camera yaw/pitch
// and the target location passed in. It does automatically adjust
// the camera's internal rotation quaternion.
func (c *Camera) LookAt(target mgl.Vec3, distance float32) {
	// use trig to get the camera position scaled by distance
	rotatedX := float32(math.Cos(float64(c.yaw))) * distance
	rotatedZ := float32(math.Sin(float64(c.yaw))) * distance

	// set the camera's location
	c.position[0] = target[0] + rotatedX
	c.position[1] = target[1] + distance
	c.position[2] = target[2] + rotatedZ

	correctedYaw := float32(math.Atan2(float64(c.position[0]-target[0]), float64(c.position[2]-target[2])))

	// update the rotation quaternion
	camYawQ := mgl.QuatRotate(-1*correctedYaw, upVector)
	camPitchQ := mgl.QuatRotate(c.pitch, sideVector)
	c.rotation = camPitchQ.Mul(camYawQ)
}

// generateRotation recalculates the rotation quaternion based on the pitch and yaw radians.
func (c *Camera) generateRotation() {
	camYawQ := mgl.QuatRotate(c.yaw, upVector)
	camPitchQ := mgl.QuatRotate(c.pitch, sideVector)
	c.rotation = camPitchQ.Mul(camYawQ)
}
<|endoftext|>