<commit_before>package sarama

import (
	"errors"
	"fmt"
)

// ErrOutOfBrokers is the error returned when the client has run out of brokers to talk to because all of them errored
// or otherwise failed to respond.
var ErrOutOfBrokers = errors.New("kafka: Client has run out of available brokers to talk to. Is your cluster reachable?")

// ErrClosedClient is the error returned when a method is called on a client that has been closed.
var ErrClosedClient = errors.New("kafka: Tried to use a client that was closed")

// ErrIncompleteResponse is the error returned when the server returns a syntactically valid response, but it does
// not contain the expected information.
var ErrIncompleteResponse = errors.New("kafka: Response did not contain all the expected topic/partition blocks")

// ErrInvalidPartition is the error returned when a partitioner returns an invalid partition index
// (meaning one outside of the range [0...numPartitions-1]).
var ErrInvalidPartition = errors.New("kafka: Partitioner returned an invalid partition index")

// ErrAlreadyConnected is the error returned when calling Open() on a Broker that is already connected or connecting.
var ErrAlreadyConnected = errors.New("kafka: broker connection already initiated")

// ErrNotConnected is the error returned when trying to send or call Close() on a Broker that is not connected.
var ErrNotConnected = errors.New("kafka: broker not connected")

// ErrInsufficientData is returned when decoding and the packet is truncated. This can be expected
// when requesting messages, since as an optimization the server is allowed to return a partial message at the end
// of the message set.

var ErrInsufficientData = errors.New("kafka: Insufficient data to decode packet, more bytes expected")

// ErrShuttingDown is returned when a producer receives a message during shutdown.
var ErrShuttingDown = errors.New("kafka: Message received by producer in process of shutting down")

// ErrMessageTooLarge is returned when the next message to consume is larger than the configured MaxFetchSize
var ErrMessageTooLarge = errors.New("kafka: Message is larger than MaxFetchSize")

// PacketEncodingError is returned from a failure while encoding a Kafka packet. This can happen, for example,
// if you try to encode a string over 2^15 characters in length, since Kafka's encoding rules do not permit that.
type PacketEncodingError struct {
	Info string
}

func (err PacketEncodingError) Error() string {
	return fmt.Sprintf("kafka: Error while encoding packet: %s", err.Info)
}

// PacketDecodingError is returned when there was an error (other than truncated data) decoding the Kafka broker's response.
// This can be a bad CRC or length field, or any other invalid value.
type PacketDecodingError struct {
	Info string
}

func (err PacketDecodingError) Error() string {
	return fmt.Sprintf("kafka: Error while decoding packet: %s", err.Info)
}

// ConfigurationError is the type of error returned from NewClient, NewAsyncProducer or NewConsumer when the specified
// configuration is invalid.
type ConfigurationError string

func (err ConfigurationError) Error() string {
	return "kafka: Invalid Configuration: " + string(err)
}

// KError is the type of error that can be returned directly by the Kafka broker.
// See https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-ErrorCodes
type KError int16

// Numeric error codes returned by the Kafka server.
const (
	ErrNoError                         KError = 0
	ErrUnknown                         KError = -1
	ErrOffsetOutOfRange                KError = 1
	ErrInvalidMessage                  KError = 2
	ErrUnknownTopicOrPartition         KError = 3
	ErrInvalidMessageSize              KError = 4
	ErrLeaderNotAvailable              KError = 5
	ErrNotLeaderForPartition           KError = 6
	ErrRequestTimedOut                 KError = 7
	ErrBrokerNotAvailable              KError = 8
	ErrReplicaNotAvailable             KError = 9
	ErrMessageSizeTooLarge             KError = 10
	ErrStaleControllerEpochCode        KError = 11
	ErrOffsetMetadataTooLarge          KError = 12
	ErrOffsetsLoadInProgress           KError = 14
	ErrConsumerCoordinatorNotAvailable KError = 15
	ErrNotCoordinatorForConsumer       KError = 16
	ErrInvalidTopic                    KError = 17
	ErrMessageSetSizeTooLarge          KError = 18
	ErrNotEnoughReplicas               KError = 19
	ErrNotEnoughReplicasAfterAppend    KError = 20
)

func (err KError) Error() string {
	// Error messages stolen/adapted from
	// https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol
	switch err {
	case ErrNoError:
		return "kafka server: Not an error, why are you printing me?"
	case ErrUnknown:
		return "kafka server: Unexpected (unknown?) server error."
	case ErrOffsetOutOfRange:
		return "kafka server: The requested offset is outside the range of offsets maintained by the server for the given topic/partition."
	case ErrInvalidMessage:
		return "kafka server: Message contents does not match its CRC."
	case ErrUnknownTopicOrPartition:
		return "kafka server: Request was for a topic or partition that does not exist on this broker."
	case ErrInvalidMessageSize:
		return "kafka server: The message has a negative size."
	case ErrLeaderNotAvailable:
		return "kafka server: In the middle of a leadership election, there is currently no leader for this partition and hence it is unavailable for writes."
	case ErrNotLeaderForPartition:
		return "kafka server: Tried to send a message to a replica that is not the leader for some partition. Your metadata is out of date."
	case ErrRequestTimedOut:
		return "kafka server: Request exceeded the user-specified time limit in the request."
	case ErrBrokerNotAvailable:
		return "kafka server: Broker not available. Not a client facing error, we should never receive this!!!"
	case ErrReplicaNotAvailable:
		return "kafka server: Replica infomation not available, one or more brokers are down."
	case ErrMessageSizeTooLarge:
		return "kafka server: Message was too large, server rejected it to avoid allocation error."
	case ErrStaleControllerEpochCode:
		return "kafka server: StaleControllerEpochCode (internal error code for broker-to-broker communication)."
	case ErrOffsetMetadataTooLarge:
		return "kafka server: Specified a string larger than the configured maximum for offset metadata."
	case ErrOffsetsLoadInProgress:
		return "kafka server: The broker is still loading offsets after a leader change for that offset's topic partition."
	case ErrConsumerCoordinatorNotAvailable:
		return "kafka server: Offset's topic has not yet been created."
	case ErrNotCoordinatorForConsumer:
		return "kafka server: Request was for a consumer group that is not coordinated by this broker."
	case ErrInvalidTopic:
		return "kafka server: The request attempted to perform an operation on an invalid topic."
	case ErrMessageSetSizeTooLarge:
		return "kafka server: The request included message batch larger than the configured segment size on the server."
	case ErrNotEnoughReplicas:
		return "kafka server: Messages are rejected since there are fewer in-sync replicas than required."
	case ErrNotEnoughReplicasAfterAppend:
		return "kafka server: Messages are written to the log, but to fewer in-sync replicas than required."
	}

	return fmt.Sprintf("Unknown error, how did this happen? Error code = %d", err)
}
<commit_msg>Update good for ConfigurationError<commit_after>package sarama

import (
	"errors"
	"fmt"
)

// ErrOutOfBrokers is the error returned when the client has run out of brokers to talk to because all of them errored
// or otherwise failed to respond.
var ErrOutOfBrokers = errors.New("kafka: Client has run out of available brokers to talk to. Is your cluster reachable?")

// ErrClosedClient is the error returned when a method is called on a client that has been closed.
var ErrClosedClient = errors.New("kafka: Tried to use a client that was closed")

// ErrIncompleteResponse is the error returned when the server returns a syntactically valid response, but it does
// not contain the expected information.
var ErrIncompleteResponse = errors.New("kafka: Response did not contain all the expected topic/partition blocks")

// ErrInvalidPartition is the error returned when a partitioner returns an invalid partition index
// (meaning one outside of the range [0...numPartitions-1]).
var ErrInvalidPartition = errors.New("kafka: Partitioner returned an invalid partition index")

// ErrAlreadyConnected is the error returned when calling Open() on a Broker that is already connected or connecting.
var ErrAlreadyConnected = errors.New("kafka: broker connection already initiated")

// ErrNotConnected is the error returned when trying to send or call Close() on a Broker that is not connected.
var ErrNotConnected = errors.New("kafka: broker not connected")

// ErrInsufficientData is returned when decoding and the packet is truncated. This can be expected
// when requesting messages, since as an optimization the server is allowed to return a partial message at the end
// of the message set.

var ErrInsufficientData = errors.New("kafka: Insufficient data to decode packet, more bytes expected")

// ErrShuttingDown is returned when a producer receives a message during shutdown.
var ErrShuttingDown = errors.New("kafka: Message received by producer in process of shutting down")

// ErrMessageTooLarge is returned when the next message to consume is larger than the configured MaxFetchSize
var ErrMessageTooLarge = errors.New("kafka: Message is larger than MaxFetchSize")

// PacketEncodingError is returned from a failure while encoding a Kafka packet. This can happen, for example,
// if you try to encode a string over 2^15 characters in length, since Kafka's encoding rules do not permit that.
type PacketEncodingError struct {
	Info string
}

func (err PacketEncodingError) Error() string {
	return fmt.Sprintf("kafka: Error while encoding packet: %s", err.Info)
}

// PacketDecodingError is returned when there was an error (other than truncated data) decoding the Kafka broker's response.
// This can be a bad CRC or length field, or any other invalid value.
type PacketDecodingError struct {
	Info string
}

func (err PacketDecodingError) Error() string {
	return fmt.Sprintf("kafka: Error while decoding packet: %s", err.Info)
}

// ConfigurationError is the type of error returned from a constructor (e.g. NewClient, or NewConsumer)
// when the specified configuration is invalid.
type ConfigurationError string

func (err ConfigurationError) Error() string {
	return "kafka: Invalid Configuration: " + string(err)
}

// KError is the type of error that can be returned directly by the Kafka broker.
// See https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol#AGuideToTheKafkaProtocol-ErrorCodes
type KError int16

// Numeric error codes returned by the Kafka server.
const (
	ErrNoError                         KError = 0
	ErrUnknown                         KError = -1
	ErrOffsetOutOfRange                KError = 1
	ErrInvalidMessage                  KError = 2
	ErrUnknownTopicOrPartition         KError = 3
	ErrInvalidMessageSize              KError = 4
	ErrLeaderNotAvailable              KError = 5
	ErrNotLeaderForPartition           KError = 6
	ErrRequestTimedOut                 KError = 7
	ErrBrokerNotAvailable              KError = 8
	ErrReplicaNotAvailable             KError = 9
	ErrMessageSizeTooLarge             KError = 10
	ErrStaleControllerEpochCode        KError = 11
	ErrOffsetMetadataTooLarge          KError = 12
	ErrOffsetsLoadInProgress           KError = 14
	ErrConsumerCoordinatorNotAvailable KError = 15
	ErrNotCoordinatorForConsumer       KError = 16
	ErrInvalidTopic                    KError = 17
	ErrMessageSetSizeTooLarge          KError = 18
	ErrNotEnoughReplicas               KError = 19
	ErrNotEnoughReplicasAfterAppend    KError = 20
)

func (err KError) Error() string {
	// Error messages stolen/adapted from
	// https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol
	switch err {
	case ErrNoError:
		return "kafka server: Not an error, why are you printing me?"
	case ErrUnknown:
		return "kafka server: Unexpected (unknown?) server error."
	case ErrOffsetOutOfRange:
		return "kafka server: The requested offset is outside the range of offsets maintained by the server for the given topic/partition."
	case ErrInvalidMessage:
		return "kafka server: Message contents does not match its CRC."
	case ErrUnknownTopicOrPartition:
		return "kafka server: Request was for a topic or partition that does not exist on this broker."
	case ErrInvalidMessageSize:
		return "kafka server: The message has a negative size."
	case ErrLeaderNotAvailable:
		return "kafka server: In the middle of a leadership election, there is currently no leader for this partition and hence it is unavailable for writes."
	case ErrNotLeaderForPartition:
		return "kafka server: Tried to send a message to a replica that is not the leader for some partition. Your metadata is out of date."
	case ErrRequestTimedOut:
		return "kafka server: Request exceeded the user-specified time limit in the request."
	case ErrBrokerNotAvailable:
		return "kafka server: Broker not available. Not a client facing error, we should never receive this!!!"
	case ErrReplicaNotAvailable:
		return "kafka server: Replica infomation not available, one or more brokers are down."
	case ErrMessageSizeTooLarge:
		return "kafka server: Message was too large, server rejected it to avoid allocation error."
	case ErrStaleControllerEpochCode:
		return "kafka server: StaleControllerEpochCode (internal error code for broker-to-broker communication)."
	case ErrOffsetMetadataTooLarge:
		return "kafka server: Specified a string larger than the configured maximum for offset metadata."
	case ErrOffsetsLoadInProgress:
		return "kafka server: The broker is still loading offsets after a leader change for that offset's topic partition."
	case ErrConsumerCoordinatorNotAvailable:
		return "kafka server: Offset's topic has not yet been created."
	case ErrNotCoordinatorForConsumer:
		return "kafka server: Request was for a consumer group that is not coordinated by this broker."
	case ErrInvalidTopic:
		return "kafka server: The request attempted to perform an operation on an invalid topic."
	case ErrMessageSetSizeTooLarge:
		return "kafka server: The request included message batch larger than the configured segment size on the server."
	case ErrNotEnoughReplicas:
		return "kafka server: Messages are rejected since there are fewer in-sync replicas than required."
	case ErrNotEnoughReplicasAfterAppend:
		return "kafka server: Messages are written to the log, but to fewer in-sync replicas than required."
	}

	return fmt.Sprintf("Unknown error, how did this happen? Error code = %d", err)
}
<|endoftext|>


<commit_before>package scrub

import (
	"fmt"
	"strings"
)

// FieldErrorCode is used to describe the reason for a field validation failure
type FieldErrorCode string

// The standard set of error codes used by the builtin field validators.
const (
	REQUIRED  FieldErrorCode = "required"
	INVALID                  = "invalid"
	MINLENGTH                = "minlength"
	MAXLENGTH                = "maxlength"
	MIN                      = "min"
	MAX                      = "max"
	MULTI                    = "multi"
	CUSTOM                   = "custom"
)

// FieldError is used to capture field validation failure information
type FieldError struct {
	Code   FieldErrorCode `json:"code"`
	Key    string         `json:"key"`
	Detail string         `json:"detail,omitempty"`
	Meta   FieldErrors    `json:"meta,omitempty"`
}

// NewFieldError creates a FieldError for fields
func NewFieldError(code FieldErrorCode, key, detail string) *FieldError {
	return &FieldError{code, key, detail, nil}
}

// NewMultiFieldError creates a FieldError for fields that embed other fields
// such as struct, map and slice fields
func NewMultiFieldError(key string, errs FieldErrors) *FieldError {
	return &FieldError{Key: key, Code: MULTI, Meta: errs}
}

func (ve *FieldError) Error() string {
	out := fmt.Sprintf("[%s] %s", ve.Code, ve.Key)
	if msg := strings.Trim(ve.Detail, " "); msg != "" {
		out = fmt.Sprintf("%s - %s", out, msg)
	}
	return out
}

// FieldErrors is an alias for a slice of field errors pointers
type FieldErrors []*FieldError

func (fe FieldErrors) Error() string {
	out := make([]string, len(fe))
	for i, e := range fe {
		out[i] = e.Error()
	}
	return strings.Join(out, "\n")
}

func describe(fe *FieldError, level int) []string {
	var out []string
	out = append(out, "* "+strings.Repeat("  ", level)+fe.Error())
	for _, e := range fe.Meta {
		n := describe(e, level+1)
		out = append(out, n...)
	}
	return out
}

// Describe recurses through a FieldErrors slice and to build a helpful string
// representation of the validation errors
func (fe FieldErrors) Describe() string {
	var out []string
	for _, e := range fe {
		o := describe(e, 0)
		out = append(out, o...)
	}
	return strings.Join(out, "\n")
}
<commit_msg>changed meta to an object instead of list to further conform to json api<commit_after>package scrub

import (
	"fmt"
	"strings"
)

// FieldErrorCode is used to describe the reason for a field validation failure
type FieldErrorCode string

// The standard set of error codes used by the builtin field validators.
const (
	REQUIRED  FieldErrorCode = "required"
	INVALID                  = "invalid"
	MINLENGTH                = "minlength"
	MAXLENGTH                = "maxlength"
	MIN                      = "min"
	MAX                      = "max"
	MULTI                    = "multi"
	CUSTOM                   = "custom"
)

type FieldErrorMeta struct {
	Fields FieldErrors `json:"fields"`
}

// FieldError is used to capture field validation failure information
type FieldError struct {
	Code   FieldErrorCode  `json:"code"`
	Key    string          `json:"key"`
	Detail string          `json:"detail,omitempty"`
	Meta   *FieldErrorMeta `json:"meta,omitempty"`
}

// NewFieldError creates a FieldError for fields
func NewFieldError(code FieldErrorCode, key, detail string) *FieldError {
	return &FieldError{code, key, detail, nil}
}

// NewMultiFieldError creates a FieldError for fields that embed other fields
// such as struct, map and slice fields
func NewMultiFieldError(key string, errs FieldErrors) *FieldError {
	return &FieldError{Key: key, Code: MULTI, Meta: &FieldErrorMeta{errs}}
}

func (ve *FieldError) Error() string {
	out := fmt.Sprintf("[%s] %s", ve.Code, ve.Key)
	if msg := strings.Trim(ve.Detail, " "); msg != "" {
		out = fmt.Sprintf("%s - %s", out, msg)
	}
	return out
}

// FieldErrors is an alias for a slice of field errors pointers
type FieldErrors []*FieldError

func (fe FieldErrors) Error() string {
	out := make([]string, len(fe))
	for i, e := range fe {
		out[i] = e.Error()
	}
	return strings.Join(out, "\n")
}

func describe(fe *FieldError, level int) []string {
	var out []string
	out = append(out, "* "+strings.Repeat("  ", level)+fe.Error())
	if meta := fe.Meta; meta != nil {
		for _, e := range fe.Meta.Fields {
			n := describe(e, level+1)
			out = append(out, n...)
		}
	}
	return out
}

// Describe recurses through a FieldErrors slice and to build a helpful string
// representation of the validation errors
func (fe FieldErrors) Describe() string {
	var out []string
	for _, e := range fe {
		o := describe(e, 0)
		out = append(out, o...)
	}
	return strings.Join(out, "\n")
}
<|endoftext|>


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

package optimize

import (
	"errors"
	"fmt"
	"math"
)

var (
	// ErrZeroDimensional signifies an optimization was called with an input of length 0.
	ErrZeroDimensional = errors.New("optimize: zero dimensional input")

	// ErrLinesearcherFailure signifies that a Linesearcher has iterated too
	// many times. This may occur if the gradient tolerance is set too low.
	ErrLinesearcherFailure = errors.New("linesearch: failed to converge")

	// ErrNonDescentDirection signifies that LinesearchMethod has received a
	// search direction from a NextDirectioner in which the function is not
	// decreasing.
	ErrNonDescentDirection = errors.New("linesearch: non-descent search direction")

	// ErrNoProgress signifies that LinesearchMethod cannot make further
	// progress because there is no change in location after Linesearcher step
	// due to floating-point arithmetic.
	ErrNoProgress = errors.New("linesearch: no change in location after Linesearcher step")
)

// ErrFunc is returned when an initial function value is invalid. The error
// state may be either +Inf or NaN. ErrFunc satisfies the error interface.
type ErrFunc float64

func (err ErrFunc) Error() string {
	switch {
	case math.IsInf(float64(err), 1):
		return "optimize: initial function value is infinite"
	case math.IsNaN(float64(err)):
		return "optimize: initial function value is NaN"
	default:
		panic("optimize: bad ErrFunc")
	}
}

// ErrGrad is returned when an initial gradient is invalid. The error gradient
// may be either ±Inf or NaN. ErrGrad satisfies the error interface.
type ErrGrad struct {
	Grad  float64 // Grad is the invalid gradient value.
	Index int     // Index is the position at which the invalid gradient was found.
}

func (err ErrGrad) Error() string {
	switch {
	case math.IsInf(err.Grad, 0):
		return fmt.Sprintf("optimize: initial gradient is infinite at position %d", err.Index)
	case math.IsNaN(err.Grad):
		return fmt.Sprintf("optimize: initial gradient is NaN at position %d", err.Index)
	default:
		panic("optimize: bad ErrGrad")
	}
}
<commit_msg>Add ErrLinesearcherBound error<commit_after>// Copyright ©2014 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package optimize

import (
	"errors"
	"fmt"
	"math"
)

var (
	// ErrZeroDimensional signifies an optimization was called with an input of length 0.
	ErrZeroDimensional = errors.New("optimize: zero dimensional input")

	// ErrLinesearcherFailure signifies that a Linesearcher has iterated too
	// many times. This may occur if the gradient tolerance is set too low.
	ErrLinesearcherFailure = errors.New("linesearch: failed to converge")

	// ErrNonDescentDirection signifies that LinesearchMethod has received a
	// search direction from a NextDirectioner in which the function is not
	// decreasing.
	ErrNonDescentDirection = errors.New("linesearch: non-descent search direction")

	// ErrNoProgress signifies that LinesearchMethod cannot make further
	// progress because there is no change in location after Linesearcher step
	// due to floating-point arithmetic.
	ErrNoProgress = errors.New("linesearch: no change in location after Linesearcher step")

	// ErrLinesearcherBound signifies that a Linesearcher reached a step that
	// lies out of allowed bounds.
	ErrLinesearcherBound = errors.New("linesearch: step out of bounds")
)

// ErrFunc is returned when an initial function value is invalid. The error
// state may be either +Inf or NaN. ErrFunc satisfies the error interface.
type ErrFunc float64

func (err ErrFunc) Error() string {
	switch {
	case math.IsInf(float64(err), 1):
		return "optimize: initial function value is infinite"
	case math.IsNaN(float64(err)):
		return "optimize: initial function value is NaN"
	default:
		panic("optimize: bad ErrFunc")
	}
}

// ErrGrad is returned when an initial gradient is invalid. The error gradient
// may be either ±Inf or NaN. ErrGrad satisfies the error interface.
type ErrGrad struct {
	Grad  float64 // Grad is the invalid gradient value.
	Index int     // Index is the position at which the invalid gradient was found.
}

func (err ErrGrad) Error() string {
	switch {
	case math.IsInf(err.Grad, 0):
		return fmt.Sprintf("optimize: initial gradient is infinite at position %d", err.Index)
	case math.IsNaN(err.Grad):
		return fmt.Sprintf("optimize: initial gradient is NaN at position %d", err.Index)
	default:
		panic("optimize: bad ErrGrad")
	}
}
<|endoftext|>


<commit_before>/*
	Go Language Raspberry Pi Interface
	(c) Copyright David Thorpe 2016-2018
	All Rights Reserved
	Documentation http://djthorpe.github.io/gopi/
	For Licensing and Usage information, please see LICENSE.md
*/

package gopi

import (
	"time"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

// Publisher is an interface for drivers which accept subscription
// and unsubscription requests
type Publisher interface {
	// Subscribe to events emitted. Returns channel on which events
	// are emitted or nil if this driver does not implement events
	Subscribe() <-chan Event

	// Unsubscribe from events emitted
	Unsubscribe(<-chan Event)
}

// Event is a generic event which is emitted through a channel
type Event interface {
	// Source of the event
	Source() Driver

	// Name of the event
	Name() string
}

// GPIOEvent implements an event from the GPIO driver
type GPIOEvent interface {
	Event

	// Pin returns the pin on which the event occurred
	Pin() GPIOPin

	// Edge returns whether the pin value is rising or falling
	// or will return NONE if not defined
	Edge() GPIOEdge
}

// LIRCEvent implements an event from the LIRC driver
type LIRCEvent interface {
	Event

	// The type of message
	Type() LIRCType

	// The value
	Value() uint32
}

// TimerEvent is emitted by the timer driver on maturity
type TimerEvent interface {
	Event

	Timestamp() time.Time
	UserInfo() interface{}
}

// InputEvent is emitted when an input device changes
type InputEvent interface {
	Event

	// Timestamp of event
	Timestamp() time.Duration

	// Type of device which has created the event
	DeviceType() InputDeviceType

	// Event type
	EventType() InputEventType

	// Device identifier
	Device() uint32

	// Key or mouse button press or release
	Keycode() KeyCode

	// Key scancode
	Scancode() uint32

	// Absolute cursor position
	Position() Point

	// Relative change in position
	Relative() Point

	// Multi-touch slot identifier
	Slot() uint
}

// RPCEvent is an event which is emitted by either discovery or
// server.
type RPCEvent interface {
	Event

	// Type of RPC Event
	Type() RPCEventType

	// Service Record when Type()==
	ServiceRecord() *RPCServiceRecord
}
<commit_msg>Updated InputEvent interface<commit_after>/*
	Go Language Raspberry Pi Interface
	(c) Copyright David Thorpe 2016-2018
	All Rights Reserved
	Documentation http://djthorpe.github.io/gopi/
	For Licensing and Usage information, please see LICENSE.md
*/

package gopi

import (
	"time"
)

////////////////////////////////////////////////////////////////////////////////
// TYPES

// Publisher is an interface for drivers which accept subscription
// and unsubscription requests
type Publisher interface {
	// Subscribe to events emitted. Returns channel on which events
	// are emitted or nil if this driver does not implement events
	Subscribe() <-chan Event

	// Unsubscribe from events emitted
	Unsubscribe(<-chan Event)
}

// Event is a generic event which is emitted through a channel
type Event interface {
	// Source of the event
	Source() Driver

	// Name of the event
	Name() string
}

// GPIOEvent implements an event from the GPIO driver
type GPIOEvent interface {
	Event

	// Pin returns the pin on which the event occurred
	Pin() GPIOPin

	// Edge returns whether the pin value is rising or falling
	// or will return NONE if not defined
	Edge() GPIOEdge
}

// LIRCEvent implements an event from the LIRC driver
type LIRCEvent interface {
	Event

	// The type of message
	Type() LIRCType

	// The value
	Value() uint32
}

// TimerEvent is emitted by the timer driver on maturity
type TimerEvent interface {
	Event

	Timestamp() time.Time
	UserInfo() interface{}
}

// InputEvent is emitted when an input device changes
type InputEvent interface {
	Event

	// Timestamp of event
	Timestamp() time.Duration

	// Type of device which has created the event
	DeviceType() InputDeviceType

	// Event type
	EventType() InputEventType

	// Device identifier
	Device() uint32

	// Key or mouse button press or release
	KeyCode() KeyCode

	// Modifier key state (caps lock, shift, alt, etc)
	KeyState() KeyState

	// Key scancode
	ScanCode() uint32

	// Absolute cursor position
	Position() Point

	// Relative change in position
	Relative() Point

	// Multi-touch slot identifier
	Slot() uint
}

// RPCEvent is an event which is emitted by either discovery or
// server.
type RPCEvent interface {
	Event

	// Type of RPC Event
	Type() RPCEventType

	// Service Record when Type()==
	ServiceRecord() *RPCServiceRecord
}
<|endoftext|>


<commit_before>package discordgo

import (
	"encoding/json"
)

// This file contains all the possible structs that can be
// handled by AddHandler/EventHandler.
// DO NOT ADD ANYTHING BUT EVENT HANDLER STRUCTS TO THIS FILE.
//go:generate go run tools/cmd/eventhandlers/main.go

// Connect is the data for a Connect event.
// This is a synthetic event and is not dispatched by Discord.
type Connect struct{}

// Disconnect is the data for a Disconnect event.
// This is a synthetic event and is not dispatched by Discord.
type Disconnect struct{}

// RateLimit is the data for a RateLimit event.
// This is a synthetic event and is not dispatched by Discord.
type RateLimit struct {
	*TooManyRequests
	URL string
}

// Event provides a basic initial struct for all websocket events.
type Event struct {
	Operation int             `json:"op"`
	Sequence  int64           `json:"s"`
	Type      string          `json:"t"`
	RawData   json.RawMessage `json:"d"`
	// Struct contains one of the other types in this file.
	Struct interface{} `json:"-"`
}

// A Ready stores all data for the websocket READY event.
type Ready struct {
	Version         int          `json:"v"`
	SessionID       string       `json:"session_id"`
	User            *User        `json:"user"`
	ReadState       []*ReadState `json:"read_state"`
	PrivateChannels []*Channel   `json:"private_channels"`
	Guilds          []*Guild     `json:"guilds"`

	// Undocumented fields
	Settings          *Settings            `json:"user_settings"`
	UserGuildSettings []*UserGuildSettings `json:"user_guild_settings"`
	Relationships     []*Relationship      `json:"relationships"`
	Presences         []*Presence          `json:"presences"`
	Notes             map[string]string    `json:"notes"`
}

// ChannelCreate is the data for a ChannelCreate event.
type ChannelCreate struct {
	*Channel
}

// ChannelUpdate is the data for a ChannelUpdate event.
type ChannelUpdate struct {
	*Channel
}

// ChannelDelete is the data for a ChannelDelete event.
type ChannelDelete struct {
	*Channel
}

// ChannelPinsUpdate stores data for a ChannelPinsUpdate event.
type ChannelPinsUpdate struct {
	LastPinTimestamp string `json:"last_pin_timestamp"`
	ChannelID        string `json:"channel_id"`
	GuildID          string `json:"guild_id,omitempty"`
}

// GuildCreate is the data for a GuildCreate event.
type GuildCreate struct {
	*Guild
}

// GuildUpdate is the data for a GuildUpdate event.
type GuildUpdate struct {
	*Guild
}

// GuildDelete is the data for a GuildDelete event.
type GuildDelete struct {
	*Guild
}

// GuildBanAdd is the data for a GuildBanAdd event.
type GuildBanAdd struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildBanRemove is the data for a GuildBanRemove event.
type GuildBanRemove struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildMemberAdd is the data for a GuildMemberAdd event.
type GuildMemberAdd struct {
	*Member
}

// GuildMemberUpdate is the data for a GuildMemberUpdate event.
type GuildMemberUpdate struct {
	*Member
}

// GuildMemberRemove is the data for a GuildMemberRemove event.
type GuildMemberRemove struct {
	*Member
}

// GuildRoleCreate is the data for a GuildRoleCreate event.
type GuildRoleCreate struct {
	*GuildRole
}

// GuildRoleUpdate is the data for a GuildRoleUpdate event.
type GuildRoleUpdate struct {
	*GuildRole
}

// A GuildRoleDelete is the data for a GuildRoleDelete event.
type GuildRoleDelete struct {
	RoleID  string `json:"role_id"`
	GuildID string `json:"guild_id"`
}

// A GuildEmojisUpdate is the data for a guild emoji update event.
type GuildEmojisUpdate struct {
	GuildID string   `json:"guild_id"`
	Emojis  []*Emoji `json:"emojis"`
}

// A GuildMembersChunk is the data for a GuildMembersChunk event.
type GuildMembersChunk struct {
	GuildID string    `json:"guild_id"`
	Members []*Member `json:"members"`
}

// GuildIntegrationsUpdate is the data for a GuildIntegrationsUpdate event.
type GuildIntegrationsUpdate struct {
	GuildID string `json:"guild_id"`
}

// MessageAck is the data for a MessageAck event.
type MessageAck struct {
	MessageID string `json:"message_id"`
	ChannelID string `json:"channel_id"`
}

// MessageCreate is the data for a MessageCreate event.
type MessageCreate struct {
	*Message
}

// MessageUpdate is the data for a MessageUpdate event.
type MessageUpdate struct {
	*Message
	// BeforeUpdate will be nil if the Message was not previously cached in the state cache.
	BeforeUpdate *Message `json:"-"`
}

// MessageDelete is the data for a MessageDelete event.
type MessageDelete struct {
	*Message
}

// MessageReactionAdd is the data for a MessageReactionAdd event.
type MessageReactionAdd struct {
	*MessageReaction
}

// MessageReactionRemove is the data for a MessageReactionRemove event.
type MessageReactionRemove struct {
	*MessageReaction
}

// MessageReactionRemoveAll is the data for a MessageReactionRemoveAll event.
type MessageReactionRemoveAll struct {
	*MessageReaction
}

// PresencesReplace is the data for a PresencesReplace event.
type PresencesReplace []*Presence

// PresenceUpdate is the data for a PresenceUpdate event.
type PresenceUpdate struct {
	Presence
	GuildID string   `json:"guild_id"`
	Roles   []string `json:"roles"`
}

// Resumed is the data for a Resumed event.
type Resumed struct {
	Trace []string `json:"_trace"`
}

// RelationshipAdd is the data for a RelationshipAdd event.
type RelationshipAdd struct {
	*Relationship
}

// RelationshipRemove is the data for a RelationshipRemove event.
type RelationshipRemove struct {
	*Relationship
}

// TypingStart is the data for a TypingStart event.
type TypingStart struct {
	UserID    string `json:"user_id"`
	ChannelID string `json:"channel_id"`
	GuildID   string `json:"guild_id,omitempty"`
	Timestamp int    `json:"timestamp"`
}

// UserUpdate is the data for a UserUpdate event.
type UserUpdate struct {
	*User
}

// UserSettingsUpdate is the data for a UserSettingsUpdate event.
type UserSettingsUpdate map[string]interface{}

// UserGuildSettingsUpdate is the data for a UserGuildSettingsUpdate event.
type UserGuildSettingsUpdate struct {
	*UserGuildSettings
}

// UserNoteUpdate is the data for a UserNoteUpdate event.
type UserNoteUpdate struct {
	ID   string `json:"id"`
	Note string `json:"note"`
}

// VoiceServerUpdate is the data for a VoiceServerUpdate event.
type VoiceServerUpdate struct {
	Token    string `json:"token"`
	GuildID  string `json:"guild_id"`
	Endpoint string `json:"endpoint"`
}

// VoiceStateUpdate is the data for a VoiceStateUpdate event.
type VoiceStateUpdate struct {
	*VoiceState
}

// MessageDeleteBulk is the data for a MessageDeleteBulk event
type MessageDeleteBulk struct {
	Messages  []string `json:"ids"`
	ChannelID string   `json:"channel_id"`
	GuildID   string   `json:"guild_id"`
}

// WebhooksUpdate is the data for a WebhooksUpdate event
type WebhooksUpdate struct {
	GuildID   string `json:"guild_id"`
	ChannelID string `json:"channel_id"`
}
<commit_msg>events: add BeforeDelete to MessageDelete<commit_after>package discordgo

import (
	"encoding/json"
)

// This file contains all the possible structs that can be
// handled by AddHandler/EventHandler.
// DO NOT ADD ANYTHING BUT EVENT HANDLER STRUCTS TO THIS FILE.
//go:generate go run tools/cmd/eventhandlers/main.go

// Connect is the data for a Connect event.
// This is a synthetic event and is not dispatched by Discord.
type Connect struct{}

// Disconnect is the data for a Disconnect event.
// This is a synthetic event and is not dispatched by Discord.
type Disconnect struct{}

// RateLimit is the data for a RateLimit event.
// This is a synthetic event and is not dispatched by Discord.
type RateLimit struct {
	*TooManyRequests
	URL string
}

// Event provides a basic initial struct for all websocket events.
type Event struct {
	Operation int             `json:"op"`
	Sequence  int64           `json:"s"`
	Type      string          `json:"t"`
	RawData   json.RawMessage `json:"d"`
	// Struct contains one of the other types in this file.
	Struct interface{} `json:"-"`
}

// A Ready stores all data for the websocket READY event.
type Ready struct {
	Version         int          `json:"v"`
	SessionID       string       `json:"session_id"`
	User            *User        `json:"user"`
	ReadState       []*ReadState `json:"read_state"`
	PrivateChannels []*Channel   `json:"private_channels"`
	Guilds          []*Guild     `json:"guilds"`

	// Undocumented fields
	Settings          *Settings            `json:"user_settings"`
	UserGuildSettings []*UserGuildSettings `json:"user_guild_settings"`
	Relationships     []*Relationship      `json:"relationships"`
	Presences         []*Presence          `json:"presences"`
	Notes             map[string]string    `json:"notes"`
}

// ChannelCreate is the data for a ChannelCreate event.
type ChannelCreate struct {
	*Channel
}

// ChannelUpdate is the data for a ChannelUpdate event.
type ChannelUpdate struct {
	*Channel
}

// ChannelDelete is the data for a ChannelDelete event.
type ChannelDelete struct {
	*Channel
}

// ChannelPinsUpdate stores data for a ChannelPinsUpdate event.
type ChannelPinsUpdate struct {
	LastPinTimestamp string `json:"last_pin_timestamp"`
	ChannelID        string `json:"channel_id"`
	GuildID          string `json:"guild_id,omitempty"`
}

// GuildCreate is the data for a GuildCreate event.
type GuildCreate struct {
	*Guild
}

// GuildUpdate is the data for a GuildUpdate event.
type GuildUpdate struct {
	*Guild
}

// GuildDelete is the data for a GuildDelete event.
type GuildDelete struct {
	*Guild
}

// GuildBanAdd is the data for a GuildBanAdd event.
type GuildBanAdd struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildBanRemove is the data for a GuildBanRemove event.
type GuildBanRemove struct {
	User    *User  `json:"user"`
	GuildID string `json:"guild_id"`
}

// GuildMemberAdd is the data for a GuildMemberAdd event.
type GuildMemberAdd struct {
	*Member
}

// GuildMemberUpdate is the data for a GuildMemberUpdate event.
type GuildMemberUpdate struct {
	*Member
}

// GuildMemberRemove is the data for a GuildMemberRemove event.
type GuildMemberRemove struct {
	*Member
}

// GuildRoleCreate is the data for a GuildRoleCreate event.
type GuildRoleCreate struct {
	*GuildRole
}

// GuildRoleUpdate is the data for a GuildRoleUpdate event.
type GuildRoleUpdate struct {
	*GuildRole
}

// A GuildRoleDelete is the data for a GuildRoleDelete event.
type GuildRoleDelete struct {
	RoleID  string `json:"role_id"`
	GuildID string `json:"guild_id"`
}

// A GuildEmojisUpdate is the data for a guild emoji update event.
type GuildEmojisUpdate struct {
	GuildID string   `json:"guild_id"`
	Emojis  []*Emoji `json:"emojis"`
}

// A GuildMembersChunk is the data for a GuildMembersChunk event.
type GuildMembersChunk struct {
	GuildID string    `json:"guild_id"`
	Members []*Member `json:"members"`
}

// GuildIntegrationsUpdate is the data for a GuildIntegrationsUpdate event.
type GuildIntegrationsUpdate struct {
	GuildID string `json:"guild_id"`
}

// MessageAck is the data for a MessageAck event.
type MessageAck struct {
	MessageID string `json:"message_id"`
	ChannelID string `json:"channel_id"`
}

// MessageCreate is the data for a MessageCreate event.
type MessageCreate struct {
	*Message
}

// MessageUpdate is the data for a MessageUpdate event.
type MessageUpdate struct {
	*Message
	// BeforeUpdate will be nil if the Message was not previously cached in the state cache.
	BeforeUpdate *Message `json:"-"`
}

// MessageDelete is the data for a MessageDelete event.
type MessageDelete struct {
	*Message
	BeforeDelete *Message `json:"-"`
}

// MessageReactionAdd is the data for a MessageReactionAdd event.
type MessageReactionAdd struct {
	*MessageReaction
}

// MessageReactionRemove is the data for a MessageReactionRemove event.
type MessageReactionRemove struct {
	*MessageReaction
}

// MessageReactionRemoveAll is the data for a MessageReactionRemoveAll event.
type MessageReactionRemoveAll struct {
	*MessageReaction
}

// PresencesReplace is the data for a PresencesReplace event.
type PresencesReplace []*Presence

// PresenceUpdate is the data for a PresenceUpdate event.
type PresenceUpdate struct {
	Presence
	GuildID string   `json:"guild_id"`
	Roles   []string `json:"roles"`
}

// Resumed is the data for a Resumed event.
type Resumed struct {
	Trace []string `json:"_trace"`
}

// RelationshipAdd is the data for a RelationshipAdd event.
type RelationshipAdd struct {
	*Relationship
}

// RelationshipRemove is the data for a RelationshipRemove event.
type RelationshipRemove struct {
	*Relationship
}

// TypingStart is the data for a TypingStart event.
type TypingStart struct {
	UserID    string `json:"user_id"`
	ChannelID string `json:"channel_id"`
	GuildID   string `json:"guild_id,omitempty"`
	Timestamp int    `json:"timestamp"`
}

// UserUpdate is the data for a UserUpdate event.
type UserUpdate struct {
	*User
}

// UserSettingsUpdate is the data for a UserSettingsUpdate event.
type UserSettingsUpdate map[string]interface{}

// UserGuildSettingsUpdate is the data for a UserGuildSettingsUpdate event.
type UserGuildSettingsUpdate struct {
	*UserGuildSettings
}

// UserNoteUpdate is the data for a UserNoteUpdate event.
type UserNoteUpdate struct {
	ID   string `json:"id"`
	Note string `json:"note"`
}

// VoiceServerUpdate is the data for a VoiceServerUpdate event.
type VoiceServerUpdate struct {
	Token    string `json:"token"`
	GuildID  string `json:"guild_id"`
	Endpoint string `json:"endpoint"`
}

// VoiceStateUpdate is the data for a VoiceStateUpdate event.
type VoiceStateUpdate struct {
	*VoiceState
}

// MessageDeleteBulk is the data for a MessageDeleteBulk event
type MessageDeleteBulk struct {
	Messages  []string `json:"ids"`
	ChannelID string   `json:"channel_id"`
	GuildID   string   `json:"guild_id"`
}

// WebhooksUpdate is the data for a WebhooksUpdate event
type WebhooksUpdate struct {
	GuildID   string `json:"guild_id"`
	ChannelID string `json:"channel_id"`
}
<|endoftext|>


<commit_before>package async

import (
  "reflect"
)

/*

  Event is a map of functions to use for a single event. The integer is the
  frequency of calls that the function should make.

*/
type Event map[reflect.Value]int

/*

  List is used for containing everything related to the events. It stores the
  name of the event, functions for the event, and number of times the function
  should be called when the event is triggered.

  All you need to do to create an event list is:
    events := make(async.Events)

  All event commands that return Events can be chained together. For example:
    events.On("myevent", func() {
      println("Called myevent")
    }).On("myevent2", func(msg string) {
      fmt.Printf("Called myevent2 with message: %s\n", msg)
    }).Emit("myevent").Emit("myevent2", "Testing")

  You can return an error from a function and it will be emitted as an error
  event. For example:
    events.On("error", func(err error) {
      fmt.Printf("Error: %s", err)
    }).On("myevent", func() error {
      return fmt.Errorf("Some error message")
    }).Emit("myevent")

  It's also easily inheritable by other structures. For example:
    type MyStruct struct {
      Events
    }

    m := MyStruct{make(async.Events)}
    m.On("myevent", func() {
      println("Called myevent")
    }).Emit("myevent")

*/
type Events map[string]Event

/*

  Clear all events out of the event list. You can supply optional names for
  the events to be cleared.

  For instance:
    events.On("test", func() {}).On("test2", func() {}).Emit("test").Clear("test")

  Returns the list of events for chaining commands.

*/
func (e Events) Clear(name ...string) Events {
  if name != nil {
    for i := 0; i < len(name); i++ {
      delete(e, name[i])
    }
    return e
  }

  for key := range e {
    delete(e, key)
  }
  return e
}

/*

  Emit an event. Arguments are optional. Each event will be ran as a Series.

  For example:
    events := make(async.Events)
    events.On("myevent", func() {
      println("Emitted myevent")
    })
    events.Emit("myevent")

  With arguments:
    events := make(async.Events)
    events.On("myevent", func(msg string) {
      fmt.Printf("Message: %s\n", msg)
    })
    events.Emit("myevent", "Testing")

  Returns the list of events for chaining commands.

*/
func (e Events) Emit(name string, args ...interface{}) Events {
  var (
    routines = make([]Routine, 0)
    values   = make([]reflect.Value, 0)
  )

  // If we don't have any events with this name, simply return.
  if e.Get(name) == nil {
    return e
  }

  // Reflect all of our arguments for the reflect.Value.Call
  for i := 0; i < len(args); i++ {
    values = append(values, reflect.ValueOf(args[i]))
  }

  for fn, freq := range e[name] {
    // Decrease frequency
    if freq > 0 {
      freq--
    }

    // If the frequency is down to 0, remove the callback from the event
    // so that it isn't triggered again.
    if freq == 0 {
      delete(e[name], fn)
    } else {
      e[name][fn] = freq
    }

    // Delete the entire event if all callbacks have been triggered
    if len(e[name]) == 0 {
      delete(e, name)
    }

    // Create the routines to pass into Series
    routines = append(routines,
      func(e Events, fn reflect.Value, values []reflect.Value) Routine {
        return func(done Done, args ...interface{}) {
          values := fn.Call(values)
          for i := 0; i < len(values); i++ {
            v := values[i].Interface()
            switch v.(type) {
            case error:
              done(v.(error))
              return
            }
          }
          done(nil)
        }
      }(e, fn, values),
    )
  }

  // Run all of the events in Series
  Series(routines, func(err error, args ...interface{}) {
    // Only emit the error event if an error was detected. Nothing else needs
    // to be done here.
    if err != nil {
      e.Emit("error", err)
    }
  })

  return e
}

/*

  Get Event map of functions and frequencies for the named event. This is just
  a convenience function. This data could also be accessed by the normal
  mapping methods.

  For instance:
    fmt.Printf("Events for myevent: %+v\n", e["myevent"])

*/
func (e Events) Get(name string) Event {
  return e[name]
}

/*

  Get length of the Event map of functions and frequencies for the named
  event. This is just a convenience function. This data could also be accessed
  by the normal mapping methods.

  For instance:
    fmt.Printf("Length: %d", len(e["myevent"]))

*/
func (e Events) Length(name string) int {
  return len(e.Get(name))
}

/*

  Add an event to be called forever.

  This is equal to calling Times with -1 as the number of times to run the
  event. More documentation can be found on the Times function.

  Returns the list of events for chaining commands.

*/
func (e Events) On(name string, callbacks ...interface{}) Events {
  return e.Times(name, -1, callbacks...)
}

/*

  Add an event to be called once.

  This is equal to calling Times with 1 as the number of times to run the
  event. More documentation can be found on the Times function.

  Returns the list of events for chaining commands.

*/
func (e Events) Once(name string, callbacks ...interface{}) Events {
  return e.Times(name, 1, callbacks...)
}

/*

  Add an event to be called a number of times. If the number of times for the
  function to be called is -1, it will be called until the list is cleared.

  Returns the list of events for chaining commands.

*/
func (e Events) Times(name string, times int, callbacks ...interface{}) Events {
  // Check to see if the event already exists. If not, create its map.
  if e[name] == nil {
    e[name] = make(Event)
  }

  for i := 0; i < len(callbacks); i++ {
    // Reflect the function so that we don't have to add function restraints.
    fn := reflect.ValueOf(callbacks[i])

    // Set the number of times that the event should run.
    e[name][fn] = times
  }

  return e
}
<commit_msg>Update Events documentation a bit<commit_after>package async

import (
  "reflect"
)

/*

  Event is a map of functions to use for a single event. The integer is the
  frequency of calls that the function should make.

*/
type Event map[reflect.Value]int

/*

  List is used for containing everything related to the events. It stores the
  name of the event, functions for the event, and number of times the function
  should be called when the event is triggered.

  All you need to do to create an event list is:
    events := make(async.Events)

  All event commands that return Events can be chained together. For example:
    events.On("myevent", func() {
      println("Called myevent")
    }).On("myevent2", func(msg string) {
      fmt.Printf("Called myevent2 with message: %s\n", msg)
    }).Emit("myevent").Emit("myevent2", "Testing")

  You can return an error from a function and it will be emitted as an error
  event. For example:
    events.On("error", func(err error) {
      fmt.Printf("Error: %s", err)
    }).On("myevent", func() error {
      return fmt.Errorf("Some error message")
    }).Emit("myevent")

  It's also easily inheritable by other structures. For example:
    type MyStruct struct {
      Events
    }

    m := MyStruct{make(async.Events)}
    m.On("myevent", func() {
      println("Called myevent")
    }).Emit("myevent")

  When you are defining your event, all function calls within that event must
  be in the same format.

  For instance, this will work fine:
    events.On("myevent", func() {}, func() {})

  However, this will NOT work:
    events.On("myevent", func() {}, func (msg string) {})

  If you were to try this second example, and then try to .Emit("myevent",
  "message") or .Emit("myevent"), you would get an error from reflect saying
  that there is too many or not enough arguments for the first function that
  is not accepting any arguments at all.

*/
type Events map[string]Event

/*

  Clear all events out of the event list. You can supply optional names for
  the events to be cleared.

  For instance:
    events.On("test", func() {}).On("test2", func() {}).Emit("test").Clear("test")

  Returns the list of events for chaining commands.

*/
func (e Events) Clear(name ...string) Events {
  if name != nil {
    for i := 0; i < len(name); i++ {
      delete(e, name[i])
    }
    return e
  }

  for key := range e {
    delete(e, key)
  }
  return e
}

/*

  Emit an event. Arguments are optional. Each event will be ran as a Series.

  For example:
    events := make(async.Events)
    events.On("myevent", func() {
      println("Emitted myevent")
    })
    events.Emit("myevent")

  With arguments:
    events := make(async.Events)
    events.On("myevent", func(msg string) {
      fmt.Printf("Message: %s\n", msg)
    })
    events.Emit("myevent", "Testing")

  Returns the list of events for chaining commands.

*/
func (e Events) Emit(name string, args ...interface{}) Events {
  var (
    routines = make([]Routine, 0)
    values   = make([]reflect.Value, 0)
  )

  // If we don't have any events with this name, simply return.
  if e.Get(name) == nil {
    return e
  }

  // Reflect all of our arguments for the reflect.Value.Call
  for i := 0; i < len(args); i++ {
    values = append(values, reflect.ValueOf(args[i]))
  }

  for fn, freq := range e[name] {
    // Decrease frequency
    if freq > 0 {
      freq--
    }

    // If the frequency is down to 0, remove the callback from the event
    // so that it isn't triggered again.
    if freq == 0 {
      delete(e[name], fn)
    } else {
      e[name][fn] = freq
    }

    // Delete the entire event if all callbacks have been triggered
    if len(e[name]) == 0 {
      delete(e, name)
    }

    // Create the routines to pass into Series
    routines = append(routines,
      func(e Events, fn reflect.Value, values []reflect.Value) Routine {
        return func(done Done, args ...interface{}) {
          values := fn.Call(values)
          for i := 0; i < len(values); i++ {
            v := values[i].Interface()
            switch v.(type) {
            case error:
              done(v.(error))
              return
            }
          }
          done(nil)
        }
      }(e, fn, values),
    )
  }

  // Run all of the events in Series
  Series(routines, func(err error, args ...interface{}) {
    // Only emit the error event if an error was detected. Nothing else needs
    // to be done here.
    if err != nil {
      e.Emit("error", err)
    }
  })

  return e
}

/*

  Get Event map of functions and frequencies for the named event. This is just
  a convenience function. This data could also be accessed by the normal
  mapping methods.

  For instance:
    fmt.Printf("Events for myevent: %+v\n", e["myevent"])

*/
func (e Events) Get(name string) Event {
  return e[name]
}

/*

  Get length of the Event map of functions and frequencies for the named
  event. This is just a convenience function. This data could also be accessed
  by the normal mapping methods.

  For instance:
    fmt.Printf("Length: %d", len(e["myevent"]))

*/
func (e Events) Length(name string) int {
  return len(e.Get(name))
}

/*

  Add an event to be called forever.

  This is equal to calling Times with -1 as the number of times to run the
  event. More documentation can be found on the Times function.

  Returns the list of events for chaining commands.

*/
func (e Events) On(name string, callbacks ...interface{}) Events {
  return e.Times(name, -1, callbacks...)
}

/*

  Add an event to be called once.

  This is equal to calling Times with 1 as the number of times to run the
  event. More documentation can be found on the Times function.

  Returns the list of events for chaining commands.

*/
func (e Events) Once(name string, callbacks ...interface{}) Events {
  return e.Times(name, 1, callbacks...)
}

/*

  Add an event to be called a number of times. If the number of times for the
  function to be called is -1, it will be called until the list is cleared.

  Returns the list of events for chaining commands.

*/
func (e Events) Times(name string, times int, callbacks ...interface{}) Events {
  // Check to see if the event already exists. If not, create its map.
  if e[name] == nil {
    e[name] = make(Event)
  }

  for i := 0; i < len(callbacks); i++ {
    // Reflect the function so that we don't have to add function restraints.
    fn := reflect.ValueOf(callbacks[i])

    // Set the number of times that the event should run.
    e[name][fn] = times
  }

  return e
}
<|endoftext|>


<commit_before>package gerrit

import (
	"time"
	"net/url"
	log "github.com/sirupsen/logrus"
)

// PatchSet contains detailed information about a specific patch set.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/json.html#patchSet
type PatchSet struct {
	Number    string      `json:"number"`
	Revision  string      `json:"revision"`
	Parents   []string    `json:"parents"`
	Ref       string      `json:"ref"`
	Uploader  AccountInfo `json:"uploader"`
	Author    AccountInfo `json:"author"`
	CreatedOn int         `json:"createdOn"`
	IsDraft   bool        `json:"isDraft"`
	Kind      string      `json:"kind"`
}

// RefUpdate contains data about a reference update.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/json.html#refUpdate
type RefUpdate struct {
	OldRev  string `json:"oldRev"`
	NewRev  string `json:"newRev"`
	RefName string `json:"refName"`
	Project string `json:"project"`
}

// EventInfo contains information about an event emitted by Gerrit.  This
// structure can be used either when parsing streamed events or when reading
// the output of the events-log plugin.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.html#events
type EventInfo struct {
	Type           string        `json:"type"`
	Change         ChangeInfo    `json:"change,omitempty"`
	PatchSet       PatchSet      `json:"patchSet,omitempty"`
	EventCreatedOn int           `json:"eventCreatedOn,omitempty"`
	Reason         string        `json:"reason,omitempty"`
	Abandoner      AccountInfo   `json:"abandoner,omitempty"`
	Restorer       AccountInfo   `json:"restorer,omitempty"`
	Submitter      AccountInfo   `json:"submitter,omitempty"`
	Author         AccountInfo   `json:"author,omitempty"`
	Uploader       AccountInfo   `json:"uploader,omitempty"`
	Approvals      []AccountInfo `json:"approvals,omitempty"`
	Comment        string        `json:"comment,omitempty"`
	Editor         AccountInfo   `json:"editor,omitempty"`
	Added          []string      `json:"added,omitempty"`
	Removed        []string      `json:"removed,omitempty"`
	Hashtags       []string      `json:"hashtags,omitempty"`
	RefUpdate      RefUpdate     `json:"refUpdate,omitempty"`
	Project        string        `json:"project,omitempty"`
	Reviewer       AccountInfo   `json:"reviewer,omitempty"`
	OldTopic       string        `json:"oldTopic,omitempty"`
	Changer        AccountInfo   `json:"changer,omitempty"`
}

// EventLogService contains functions for querying the API provided
// by the optional events-log plugin.
type EventsLogService struct {
	client *Client
}

// EventLogService contains options for querying events from the events-logs
// plugin.
type EventsLogOptions struct {
	From *time.Time
	To   *time.Time
}

// getURL returns the url that should be used in the request.  This will vary
// depending on the options provided to GetEvents.
func (events *EventsLogService) getURL(options *EventsLogOptions) (string, error) {
	parsedUrl, err := url.Parse("/plugins/events-log/events/")

	if err != nil {
		return "", err
	}

	query := parsedUrl.Query()

	if options.From != nil {
		query.Set("t1", options.From.Format("2006-01-02 15:04:05"))
	}

	if options.To != nil {
		query.Set("t2", options.To.Format("2006-01-02 15:04:05"))
	}

	return parsedUrl.String(), nil
}

// GetEvents returns a list of events for the given input options.  Use of this
// function an authenticated user.
//
// Gerrit API docs: https://<yourserver>/plugins/events-log/Documentation/rest-api-events.html
func (events *EventsLogService) GetEvents(options *EventsLogOptions) (*[]EventInfo, *Response, error) {
	url, err := events.getURL(options)
	log.Info(url)

	if err != nil {
		return nil, nil, err
	}

	request, err := events.client.NewRequest("GET", url, nil)
	if err != nil {
		return nil, nil, err
	}

	var eventInfo *[]EventInfo

	response, err := events.client.Do(request, eventInfo)
	if err != nil {
		return nil, nil, err
	}

	return eventInfo, response, err

}
<commit_msg>handle response in GetEvents() rather than passing it into events.client.Do<commit_after>package gerrit

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/url"
	"time"
)

// PatchSet contains detailed information about a specific patch set.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/json.html#patchSet
type PatchSet struct {
	Number    string      `json:"number"`
	Revision  string      `json:"revision"`
	Parents   []string    `json:"parents"`
	Ref       string      `json:"ref"`
	Uploader  AccountInfo `json:"uploader"`
	Author    AccountInfo `json:"author"`
	CreatedOn int         `json:"createdOn"`
	IsDraft   bool        `json:"isDraft"`
	Kind      string      `json:"kind"`
}

// RefUpdate contains data about a reference update.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/json.html#refUpdate
type RefUpdate struct {
	OldRev  string `json:"oldRev"`
	NewRev  string `json:"newRev"`
	RefName string `json:"refName"`
	Project string `json:"project"`
}

// EventInfo contains information about an event emitted by Gerrit.  This
// structure can be used either when parsing streamed events or when reading
// the output of the events-log plugin.
//
// Gerrit API docs: https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.html#events
type EventInfo struct {
	Type           string        `json:"type"`
	Change         ChangeInfo    `json:"change,omitempty"`
	PatchSet       PatchSet      `json:"patchSet,omitempty"`
	EventCreatedOn int           `json:"eventCreatedOn,omitempty"`
	Reason         string        `json:"reason,omitempty"`
	Abandoner      AccountInfo   `json:"abandoner,omitempty"`
	Restorer       AccountInfo   `json:"restorer,omitempty"`
	Submitter      AccountInfo   `json:"submitter,omitempty"`
	Author         AccountInfo   `json:"author,omitempty"`
	Uploader       AccountInfo   `json:"uploader,omitempty"`
	Approvals      []AccountInfo `json:"approvals,omitempty"`
	Comment        string        `json:"comment,omitempty"`
	Editor         AccountInfo   `json:"editor,omitempty"`
	Added          []string      `json:"added,omitempty"`
	Removed        []string      `json:"removed,omitempty"`
	Hashtags       []string      `json:"hashtags,omitempty"`
	RefUpdate      RefUpdate     `json:"refUpdate,omitempty"`
	Project        string        `json:"project,omitempty"`
	Reviewer       AccountInfo   `json:"reviewer,omitempty"`
	OldTopic       string        `json:"oldTopic,omitempty"`
	Changer        AccountInfo   `json:"changer,omitempty"`
}

// EventLogService contains functions for querying the API provided
// by the optional events-log plugin.
type EventsLogService struct {
	client *Client
}

// EventLogService contains options for querying events from the events-logs
// plugin.
type EventsLogOptions struct {
	From *time.Time
	To   *time.Time
}

// getURL returns the url that should be used in the request.  This will vary
// depending on the options provided to GetEvents.
func (events *EventsLogService) getURL(options *EventsLogOptions) (string, error) {
	parsedUrl, err := url.Parse("/plugins/events-log/events/")

	if err != nil {
		return "", err
	}

	query := parsedUrl.Query()

	if options.From != nil {
		query.Set("t1", options.From.Format("2006-01-02 15:04:05"))
	}

	if options.To != nil {
		query.Set("t2", options.To.Format("2006-01-02 15:04:05"))
	}

	return parsedUrl.String(), nil
}

// GetEvents returns a list of events for the given input options.  Use of this
// function an authenticated user.
//
// Gerrit API docs: https://<yourserver>/plugins/events-log/Documentation/rest-api-events.html
func (events *EventsLogService) GetEvents(options *EventsLogOptions) (*[]EventInfo, *Response, error) {
	url, err := events.getURL(options)
	if err != nil {
		return nil, nil, err
	}

	request, err := events.client.NewRequest("GET", url, nil)
	if err != nil {
		return nil, nil, err
	}

	// Perform the request but do not pass in a structure to unpack
	// the response into.  The format of the response is one EventInfo
	// object per line so we need to manually handle the response here.
	response, err := events.client.Do(request, nil)
	if err != nil {
		return nil, nil, err
	}

	body, err := ioutil.ReadAll(response.Body)

	defer response.Body.Close()
	if err != nil {
		return nil, nil, err
	}

	eventInfo := new([]EventInfo)
	for _, line := range bytes.Split(body, []byte("\n")) {
		if len(line) > 0 {
			event := EventInfo{}
			err := json.Unmarshal(line, &event)
			if err != nil {
				return nil, nil, err
			}
			*eventInfo = append(*eventInfo, event)
		}
	}

	return eventInfo, response, err
}
<|endoftext|>


<commit_before>package integration_test

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/blang/semver"
	"github.com/cloudfoundry/libbuildpack"
	"github.com/cloudfoundry/libbuildpack/cutlass"
	"github.com/sclevine/agouti"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

var bpDir string
var buildpackVersion string
var packagedBuildpack cutlass.VersionedBuildpackPackage
var agoutiDriver *agouti.WebDriver

func init() {
	flag.StringVar(&buildpackVersion, "version", "", "version to use (builds if empty)")
	flag.BoolVar(&cutlass.Cached, "cached", true, "cached buildpack")
	flag.StringVar(&cutlass.DefaultMemory, "memory", "256M", "default memory for pushed apps")
	flag.StringVar(&cutlass.DefaultDisk, "disk", "512M", "default disk for pushed apps")
	flag.Parse()
}

var _ = SynchronizedBeforeSuite(func() []byte {
	// Run once
	if buildpackVersion == "" {
		packagedBuildpack, err := cutlass.PackageUniquelyVersionedBuildpack()
		Expect(err).NotTo(HaveOccurred())

		data, err := json.Marshal(packagedBuildpack)
		Expect(err).NotTo(HaveOccurred())
		return data
	}

	return []byte{}
}, func(data []byte) {
	// Run on all nodes
	var err error
	if len(data) > 0 {
		err = json.Unmarshal(data, &packagedBuildpack)
		Expect(err).NotTo(HaveOccurred())
		buildpackVersion = packagedBuildpack.Version
	}

	bpDir, err = cutlass.FindRoot()
	Expect(err).NotTo(HaveOccurred())

	Expect(cutlass.CopyCfHome()).To(Succeed())

	cutlass.SeedRandom()
	cutlass.DefaultStdoutStderr = GinkgoWriter

	// agoutiDriver = agouti.PhantomJS()
	// agoutiDriver = agouti.Selenium()
	agoutiDriver = agouti.ChromeDriver(agouti.ChromeOptions("args", []string{"--headless", "--disable-gpu"}))
	Expect(agoutiDriver.Start()).To(Succeed())
})

var _ = SynchronizedAfterSuite(func() {
	// Run on all nodes
	Expect(agoutiDriver.Stop()).To(Succeed())
}, func() {
	// Run once
	cutlass.RemovePackagedBuildpack(packagedBuildpack)
	Expect(cutlass.DeleteOrphanedRoutes()).To(Succeed())
})

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Integration Suite")
}

func PushAppAndConfirm(app *cutlass.App) {
	Expect(app.Push()).To(Succeed())
	Eventually(func() ([]string, error) { return app.InstanceStates() }, 20*time.Second).Should(Equal([]string{"RUNNING"}))
	Expect(app.ConfirmBuildpack(buildpackVersion)).To(Succeed())
}

func Restart(app *cutlass.App) {
	Expect(app.Restart()).To(Succeed())
	Eventually(func() ([]string, error) { return app.InstanceStates() }, 20*time.Second).Should(Equal([]string{"RUNNING"}))
}

func ApiHasTask() bool {
	apiVersionString, err := cutlass.ApiVersion()
	Expect(err).To(BeNil())
	apiVersion, err := semver.Make(apiVersionString)
	Expect(err).To(BeNil())
	apiHasTask, err := semver.ParseRange(">= 2.75.0")
	Expect(err).To(BeNil())
	return apiHasTask(apiVersion)
}
func ApiHasMultiBuildpack() bool {
	apiVersionString, err := cutlass.ApiVersion()
	Expect(err).To(BeNil())
	apiVersion, err := semver.Make(apiVersionString)
	Expect(err).To(BeNil())
	apiHasTask, err := semver.ParseRange(">= 3.27.0")
	Expect(err).To(BeNil())
	return apiHasTask(apiVersion)
}

func SkipUnlessUncached() {
	if cutlass.Cached {
		Skip("Running cached tests")
	}
}

func SkipUnlessCached() {
	if !cutlass.Cached {
		Skip("Running uncached tests")
	}
}

func DestroyApp(app *cutlass.App) *cutlass.App {
	if app != nil {
		app.Destroy()
	}
	return nil
}

func DefaultVersion(name string) string {
	m := &libbuildpack.Manifest{}
	err := (&libbuildpack.YAML{}).Load(filepath.Join(bpDir, "manifest.yml"), m)
	Expect(err).ToNot(HaveOccurred())
	dep, err := m.DefaultVersion(name)
	Expect(err).ToNot(HaveOccurred())
	Expect(dep.Version).ToNot(Equal(""))
	return dep.Version
}

func AssertUsesProxyDuringStagingIfPresent(fixtureName string) {
	Context("with an uncached buildpack", func() {
		BeforeEach(SkipUnlessUncached)

		It("uses a proxy during staging if present", func() {
			proxy, err := cutlass.NewProxy()
			Expect(err).To(BeNil())
			defer proxy.Close()

			bpFile := filepath.Join(bpDir, buildpackVersion+"tmp")
			cmd := exec.Command("cp", packagedBuildpack.File, bpFile)
			err = cmd.Run()
			Expect(err).To(BeNil())
			defer os.Remove(bpFile)

			traffic, err := cutlass.InternetTraffic(
				bpDir,
				filepath.Join("fixtures", fixtureName),
				bpFile,
				[]string{"HTTP_PROXY=" + proxy.URL, "HTTPS_PROXY=" + proxy.URL},
			)
			Expect(err).To(BeNil())

			destUrl, err := url.Parse(proxy.URL)
			Expect(err).To(BeNil())

			Expect(cutlass.UniqueDestination(
				traffic, fmt.Sprintf("%s.%s", destUrl.Hostname(), destUrl.Port()),
			)).To(BeNil())
		})
	})
}

func AssertNoInternetTraffic(fixtureName string) {
	It("has no traffic", func() {
		SkipUnlessCached()

		bpFile := filepath.Join(bpDir, buildpackVersion+"tmp")
		cmd := exec.Command("cp", packagedBuildpack.File, bpFile)
		err := cmd.Run()
		Expect(err).To(BeNil())
		defer os.Remove(bpFile)

		traffic, err := cutlass.InternetTraffic(
			bpDir,
			filepath.Join("fixtures", fixtureName),
			bpFile,
			[]string{},
		)
		Expect(err).To(BeNil())
		Expect(traffic).To(BeEmpty())
	})
}
<commit_msg>Add --no-sandbox option to ChromeDriver to make it work in docker<commit_after>package integration_test

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/blang/semver"
	"github.com/cloudfoundry/libbuildpack"
	"github.com/cloudfoundry/libbuildpack/cutlass"
	"github.com/sclevine/agouti"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"testing"
)

var bpDir string
var buildpackVersion string
var packagedBuildpack cutlass.VersionedBuildpackPackage
var agoutiDriver *agouti.WebDriver

func init() {
	flag.StringVar(&buildpackVersion, "version", "", "version to use (builds if empty)")
	flag.BoolVar(&cutlass.Cached, "cached", true, "cached buildpack")
	flag.StringVar(&cutlass.DefaultMemory, "memory", "256M", "default memory for pushed apps")
	flag.StringVar(&cutlass.DefaultDisk, "disk", "512M", "default disk for pushed apps")
	flag.Parse()
}

var _ = SynchronizedBeforeSuite(func() []byte {
	// Run once
	if buildpackVersion == "" {
		packagedBuildpack, err := cutlass.PackageUniquelyVersionedBuildpack()
		Expect(err).NotTo(HaveOccurred())

		data, err := json.Marshal(packagedBuildpack)
		Expect(err).NotTo(HaveOccurred())
		return data
	}

	return []byte{}
}, func(data []byte) {
	// Run on all nodes
	var err error
	if len(data) > 0 {
		err = json.Unmarshal(data, &packagedBuildpack)
		Expect(err).NotTo(HaveOccurred())
		buildpackVersion = packagedBuildpack.Version
	}

	bpDir, err = cutlass.FindRoot()
	Expect(err).NotTo(HaveOccurred())

	Expect(cutlass.CopyCfHome()).To(Succeed())

	cutlass.SeedRandom()
	cutlass.DefaultStdoutStderr = GinkgoWriter

	// agoutiDriver = agouti.PhantomJS()
	// agoutiDriver = agouti.Selenium()
	agoutiDriver = agouti.ChromeDriver(agouti.ChromeOptions("args", []string{"--headless", "--disable-gpu", "--no-sandbox"}))
	Expect(agoutiDriver.Start()).To(Succeed())
})

var _ = SynchronizedAfterSuite(func() {
	// Run on all nodes
	Expect(agoutiDriver.Stop()).To(Succeed())
}, func() {
	// Run once
	cutlass.RemovePackagedBuildpack(packagedBuildpack)
	Expect(cutlass.DeleteOrphanedRoutes()).To(Succeed())
})

func TestIntegration(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Integration Suite")
}

func PushAppAndConfirm(app *cutlass.App) {
	Expect(app.Push()).To(Succeed())
	Eventually(func() ([]string, error) { return app.InstanceStates() }, 20*time.Second).Should(Equal([]string{"RUNNING"}))
	Expect(app.ConfirmBuildpack(buildpackVersion)).To(Succeed())
}

func Restart(app *cutlass.App) {
	Expect(app.Restart()).To(Succeed())
	Eventually(func() ([]string, error) { return app.InstanceStates() }, 20*time.Second).Should(Equal([]string{"RUNNING"}))
}

func ApiHasTask() bool {
	apiVersionString, err := cutlass.ApiVersion()
	Expect(err).To(BeNil())
	apiVersion, err := semver.Make(apiVersionString)
	Expect(err).To(BeNil())
	apiHasTask, err := semver.ParseRange(">= 2.75.0")
	Expect(err).To(BeNil())
	return apiHasTask(apiVersion)
}
func ApiHasMultiBuildpack() bool {
	apiVersionString, err := cutlass.ApiVersion()
	Expect(err).To(BeNil())
	apiVersion, err := semver.Make(apiVersionString)
	Expect(err).To(BeNil())
	apiHasTask, err := semver.ParseRange(">= 3.27.0")
	Expect(err).To(BeNil())
	return apiHasTask(apiVersion)
}

func SkipUnlessUncached() {
	if cutlass.Cached {
		Skip("Running cached tests")
	}
}

func SkipUnlessCached() {
	if !cutlass.Cached {
		Skip("Running uncached tests")
	}
}

func DestroyApp(app *cutlass.App) *cutlass.App {
	if app != nil {
		app.Destroy()
	}
	return nil
}

func DefaultVersion(name string) string {
	m := &libbuildpack.Manifest{}
	err := (&libbuildpack.YAML{}).Load(filepath.Join(bpDir, "manifest.yml"), m)
	Expect(err).ToNot(HaveOccurred())
	dep, err := m.DefaultVersion(name)
	Expect(err).ToNot(HaveOccurred())
	Expect(dep.Version).ToNot(Equal(""))
	return dep.Version
}

func AssertUsesProxyDuringStagingIfPresent(fixtureName string) {
	Context("with an uncached buildpack", func() {
		BeforeEach(SkipUnlessUncached)

		It("uses a proxy during staging if present", func() {
			proxy, err := cutlass.NewProxy()
			Expect(err).To(BeNil())
			defer proxy.Close()

			bpFile := filepath.Join(bpDir, buildpackVersion+"tmp")
			cmd := exec.Command("cp", packagedBuildpack.File, bpFile)
			err = cmd.Run()
			Expect(err).To(BeNil())
			defer os.Remove(bpFile)

			traffic, err := cutlass.InternetTraffic(
				bpDir,
				filepath.Join("fixtures", fixtureName),
				bpFile,
				[]string{"HTTP_PROXY=" + proxy.URL, "HTTPS_PROXY=" + proxy.URL},
			)
			Expect(err).To(BeNil())

			destUrl, err := url.Parse(proxy.URL)
			Expect(err).To(BeNil())

			Expect(cutlass.UniqueDestination(
				traffic, fmt.Sprintf("%s.%s", destUrl.Hostname(), destUrl.Port()),
			)).To(BeNil())
		})
	})
}

func AssertNoInternetTraffic(fixtureName string) {
	It("has no traffic", func() {
		SkipUnlessCached()

		bpFile := filepath.Join(bpDir, buildpackVersion+"tmp")
		cmd := exec.Command("cp", packagedBuildpack.File, bpFile)
		err := cmd.Run()
		Expect(err).To(BeNil())
		defer os.Remove(bpFile)

		traffic, err := cutlass.InternetTraffic(
			bpDir,
			filepath.Join("fixtures", fixtureName),
			bpFile,
			[]string{},
		)
		Expect(err).To(BeNil())
		Expect(traffic).To(BeEmpty())
	})
}
<|endoftext|>


<commit_before>package main

import "path/filepath"
import "os"

func FileExists(path string) (bool, error) {
	file, err := os.Open(path) // For read access.
	if err != nil {
		return false, err
	}
	_, err = file.Stat()
	if err != nil {
		return false, err
	}
	return true, nil
}

func IsDir(path string) (bool, error) {
	return DirExists(path)
}

func DirExists(path string) (bool, error) {
	file, err := os.Open(path) // For read access.
	if err != nil {
		return false, err
	}
	stat, err := file.Stat()
	if err != nil {
		return false, err
	}
	return stat.IsDir(), nil
}

func Subfolders(path string) (paths []string) {
	filepath.Walk(path, func(newPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			name := info.Name()
			// skip folders that begin with a dot
			hidden := filepath.HasPrefix(name, ".") && name != "." && name != ".."
			if hidden {
				return filepath.SkipDir
			} else {
				paths = append(paths, newPath)
			}
		}
		return nil
	})
	return paths
}
<commit_msg>should close files<commit_after>package main

import "path/filepath"
import "os"

func FileExists(path string) (bool, error) {
	file, err := os.Open(path) // For read access.
	if err != nil {
		return false, err
	}
	_, err = file.Stat()
	if err != nil {
		return false, err
	}
	err = file.Close()
	if err != nil {
		return false, err
	}
	return true, nil
}

func IsDir(path string) (bool, error) {
	return DirExists(path)
}

func DirExists(path string) (bool, error) {
	file, err := os.Open(path) // For read access.
	if err != nil {
		return false, err
	}
	stat, err := file.Stat()
	if err != nil {
		return false, err
	}
	err = file.Close()
	if err != nil {
		return false, err
	}
	return stat.IsDir(), nil
}

func Subfolders(path string) (paths []string) {
	filepath.Walk(path, func(newPath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if info.IsDir() {
			name := info.Name()
			// skip folders that begin with a dot
			hidden := filepath.HasPrefix(name, ".") && name != "." && name != ".."
			if hidden {
				return filepath.SkipDir
			} else {
				paths = append(paths, newPath)
			}
		}
		return nil
	})
	return paths
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdExport = &Command{
	Run:   runExport,
	Usage: "export [dir]",
	Short: "Export metadata to a local directory",
	Long: `
Export metadata to a local directory

Examples:

  force export

  force export org/schema
`,
}

func getMetadataType(metadataType string, folders map[string]string) (member []string) {
	force, _ := ActiveForce()
	var queryString string
	if metadataType == "Report" {
		queryString = "SELECT Id, OwnerId ,DeveloperName from Report"
	} else {
		queryString = "SELECT Id, DeveloperName, Folder.DeveloperName from " + metadataType
	}
	queryResult, _, _ := force.Query(fmt.Sprintf("%s", queryString), false)
	metadataItems := make([]string, 1, 1000)
	metadataItems[0] = "*"
	for _, folderName := range folders {
		metadataItems = append(metadataItems, folderName)
	}

	for _, metadataItem := range queryResult.Records {
		folderName := ""
		if metadataType == "Report" {
			folderName, _ = folders[metadataItem["OwnerId"].(string)]
		} else {
			folderData, _ := metadataItem["Folder"].(map[string]interface{})
			if folderData != nil {
				folderName = folderData["DeveloperName"].(string)
			}
		}
		if folderName != "" {
			metadataItems = append(metadataItems, folderName+"/"+metadataItem["DeveloperName"].(string))
		}
	}
	return metadataItems
}

func runExport(cmd *Command, args []string) {
	// Get path from args if available
	var err error
	var root string
	if len(args) == 1 {
		root, err = filepath.Abs(args[0])
	}
	if err != nil {
		fmt.Printf("Error obtaining file path\n")
		ErrorAndExit(err.Error())
	}
	force, _ := ActiveForce()
	sobjects, err := force.ListSobjects()
	if err != nil {
		ErrorAndExit(err.Error())
	}
	stdObjects := make([]string, 1, len(sobjects)+1)
	stdObjects[0] = "*"
	for _, sobject := range sobjects {
		name := sobject["name"].(string)
		if !sobject["custom"].(bool) && !strings.HasSuffix(name, "__Tag") && !strings.HasSuffix(name, "__History") && !strings.HasSuffix(name, "__Share") {
			stdObjects = append(stdObjects, name)
		}
	}
	query := ForceMetadataQuery{
		{Name: "AccountSettings", Members: []string{"*"}},
		{Name: "ActivitiesSettings", Members: []string{"*"}},
		{Name: "AddressSettings", Members: []string{"*"}},
		{Name: "AnalyticSnapshot", Members: []string{"*"}},
		{Name: "ApexClass", Members: []string{"*"}},
		{Name: "ApexComponent", Members: []string{"*"}},
		{Name: "ApexPage", Members: []string{"*"}},
		{Name: "ApexTrigger", Members: []string{"*"}},
		{Name: "ApprovalProcess", Members: []string{"*"}},
		{Name: "AssignmentRules", Members: []string{"*"}},
		{Name: "AuthProvider", Members: []string{"*"}},
		{Name: "AutoResponseRules", Members: []string{"*"}},
		{Name: "BusinessHoursSettings", Members: []string{"*"}},
		{Name: "BusinessProcess", Members: []string{"*"}},
		{Name: "CallCenter", Members: []string{"*"}},
		{Name: "CaseSettings", Members: []string{"*"}},
		{Name: "ChatterAnswersSettings", Members: []string{"*"}},
		{Name: "CompanySettings", Members: []string{"*"}},
		{Name: "Community", Members: []string{"*"}},
		{Name: "CompactLayout", Members: []string{"*"}},
		{Name: "ConnectedApp", Members: []string{"*"}},
		{Name: "ContractSettings", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomApplicationComponent", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomField", Members: []string{"*"}},
		{Name: "CustomLabels", Members: []string{"*"}},
		{Name: "CustomMetadata", Members: []string("*")},
		{Name: "CustomObject", Members: stdObjects},
		{Name: "CustomObjectTranslation", Members: []string{"*"}},
		{Name: "CustomPageWebLink", Members: []string{"*"}},
		{Name: "CustomPermission", Members: []string{"*"}},
		{Name: "CustomSite", Members: []string{"*"}},
		{Name: "CustomTab", Members: []string{"*"}},
		{Name: "DataCategoryGroup", Members: []string{"*"}},
		{Name: "EntitlementProcess", Members: []string{"*"}},
		{Name: "EntitlementSettings", Members: []string{"*"}},
		{Name: "EntitlementTemplate", Members: []string{"*"}},
		{Name: "ExternalDataSource", Members: []string{"*"}},
		{Name: "FieldSet", Members: []string{"*"}},
		{Name: "Flow", Members: []string{"*"}},
		{Name: "Folder", Members: []string{"*"}},
		{Name: "ForecastingSettings", Members: []string{"*"}},
		{Name: "Group", Members: []string{"*"}},
		{Name: "HomePageComponent", Members: []string{"*"}},
		{Name: "HomePageLayout", Members: []string{"*"}},
		{Name: "IdeasSettings", Members: []string{"*"}},
		{Name: "KnowledgeSettings", Members: []string{"*"}},
		{Name: "Layout", Members: []string{"*"}},
		{Name: "Letterhead", Members: []string{"*"}},
		{Name: "ListView", Members: []string{"*"}},
		{Name: "LiveAgentSettings", Members: []string{"*"}},
		{Name: "LiveChatAgentConfig", Members: []string{"*"}},
		{Name: "LiveChatButton", Members: []string{"*"}},
		{Name: "LiveChatDeployment", Members: []string{"*"}},
		{Name: "MilestoneType", Members: []string{"*"}},
		{Name: "MobileSettings", Members: []string{"*"}},
		{Name: "NamedFilter", Members: []string{"*"}},
		{Name: "Network", Members: []string{"*"}},
		{Name: "OpportunitySettings", Members: []string{"*"}},
		{Name: "PermissionSet", Members: []string{"*"}},
		{Name: "Portal", Members: []string{"*"}},
		{Name: "PostTemplate", Members: []string{"*"}},
		{Name: "ProductSettings", Members: []string{"*"}},
		{Name: "Profile", Members: []string{"*"}},
		{Name: "Queue", Members: []string{"*"}},
		{Name: "QuickAction", Members: []string{"*"}},
		{Name: "QuoteSettings", Members: []string{"*"}},
		{Name: "RecordType", Members: []string{"*"}},
		{Name: "RemoteSiteSetting", Members: []string{"*"}},
		{Name: "ReportType", Members: []string{"*"}},
		{Name: "Role", Members: []string{"*"}},
		{Name: "SamlSsoConfig", Members: []string{"*"}},
		{Name: "Scontrol", Members: []string{"*"}},
		{Name: "SecuritySettings", Members: []string{"*"}},
		{Name: "SharingReason", Members: []string{"*"}},
		{Name: "SharingRules", Members: []string{"*"}},
		{Name: "Skill", Members: []string{"*"}},
		{Name: "StaticResource", Members: []string{"*"}},
		{Name: "Territory", Members: []string{"*"}},
		{Name: "Translations", Members: []string{"*"}},
		{Name: "ValidationRule", Members: []string{"*"}},
		{Name: "Workflow", Members: []string{"*"}},
	}

	folderResult, _, err := force.Query(fmt.Sprintf("%s", "SELECT Id, Type, DeveloperName from Folder"), false)
	folders := make(map[string]map[string]string)
	for _, folder := range folderResult.Records {
		if folder["DeveloperName"] != nil {
			folderType := folder["Type"].(string)
			m, ok := folders[folderType]
			if !ok {
				m = make(map[string]string)
				folders[folderType] = m
			}
			m[folder["Id"].(string)] = folder["DeveloperName"].(string)
		}
	}
	for foldersType, foldersName := range folders {
		if foldersType == "Email" {
			foldersType = "EmailTemplate"
		}
		members := getMetadataType(foldersType, foldersName)
		query = append(query, ForceMetadataQueryElement{Name: foldersType, Members: members})
	}

	root, err = GetSourceDir()
	if err != nil {
		fmt.Printf("Error obtaining root directory\n")
		ErrorAndExit(err.Error())
	}
	files, err := force.Metadata.Retrieve(query)
	if err != nil {
		fmt.Printf("Encountered and error with retrieve...\n")
		ErrorAndExit(err.Error())
	}
	for name, data := range files {
		file := filepath.Join(root, name)
		dir := filepath.Dir(file)
		if err := os.MkdirAll(dir, 0755); err != nil {
			ErrorAndExit(err.Error())
		}
		if err := ioutil.WriteFile(filepath.Join(root, name), data, 0644); err != nil {
			ErrorAndExit(err.Error())
		}
	}
	fmt.Printf("Exported to %s\n", root)
}
<commit_msg>add AuraDefinitionBundle to export<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

var cmdExport = &Command{
	Run:   runExport,
	Usage: "export [dir]",
	Short: "Export metadata to a local directory",
	Long: `
Export metadata to a local directory

Examples:

  force export

  force export org/schema
`,
}

func getMetadataType(metadataType string, folders map[string]string) (member []string) {
	force, _ := ActiveForce()
	var queryString string
	if metadataType == "Report" {
		queryString = "SELECT Id, OwnerId ,DeveloperName from Report"
	} else {
		queryString = "SELECT Id, DeveloperName, Folder.DeveloperName from " + metadataType
	}
	queryResult, _, _ := force.Query(fmt.Sprintf("%s", queryString), false)
	metadataItems := make([]string, 1, 1000)
	metadataItems[0] = "*"
	for _, folderName := range folders {
		metadataItems = append(metadataItems, folderName)
	}

	for _, metadataItem := range queryResult.Records {
		folderName := ""
		if metadataType == "Report" {
			folderName, _ = folders[metadataItem["OwnerId"].(string)]
		} else {
			folderData, _ := metadataItem["Folder"].(map[string]interface{})
			if folderData != nil {
				folderName = folderData["DeveloperName"].(string)
			}
		}
		if folderName != "" {
			metadataItems = append(metadataItems, folderName+"/"+metadataItem["DeveloperName"].(string))
		}
	}
	return metadataItems
}

func runExport(cmd *Command, args []string) {
	// Get path from args if available
	var err error
	var root string
	if len(args) == 1 {
		root, err = filepath.Abs(args[0])
	}
	if err != nil {
		fmt.Printf("Error obtaining file path\n")
		ErrorAndExit(err.Error())
	}
	force, _ := ActiveForce()
	sobjects, err := force.ListSobjects()
	if err != nil {
		ErrorAndExit(err.Error())
	}
	stdObjects := make([]string, 1, len(sobjects)+1)
	stdObjects[0] = "*"
	for _, sobject := range sobjects {
		name := sobject["name"].(string)
		if !sobject["custom"].(bool) && !strings.HasSuffix(name, "__Tag") && !strings.HasSuffix(name, "__History") && !strings.HasSuffix(name, "__Share") {
			stdObjects = append(stdObjects, name)
		}
	}
	query := ForceMetadataQuery{
		{Name: "AccountSettings", Members: []string{"*"}},
		{Name: "ActivitiesSettings", Members: []string{"*"}},
		{Name: "AddressSettings", Members: []string{"*"}},
		{Name: "AnalyticSnapshot", Members: []string{"*"}},
		{Name: "ApexClass", Members: []string{"*"}},
		{Name: "ApexComponent", Members: []string{"*"}},
		{Name: "ApexPage", Members: []string{"*"}},
		{Name: "ApexTrigger", Members: []string{"*"}},
		{Name: "ApprovalProcess", Members: []string{"*"}},
		{Name: "AssignmentRules", Members: []string{"*"}},
		{Name: "AuraDefinitionBundle", Members: []string{"*"}},
		{Name: "AuthProvider", Members: []string{"*"}},
		{Name: "AutoResponseRules", Members: []string{"*"}},
		{Name: "BusinessHoursSettings", Members: []string{"*"}},
		{Name: "BusinessProcess", Members: []string{"*"}},
		{Name: "CallCenter", Members: []string{"*"}},
		{Name: "CaseSettings", Members: []string{"*"}},
		{Name: "ChatterAnswersSettings", Members: []string{"*"}},
		{Name: "CompanySettings", Members: []string{"*"}},
		{Name: "Community", Members: []string{"*"}},
		{Name: "CompactLayout", Members: []string{"*"}},
		{Name: "ConnectedApp", Members: []string{"*"}},
		{Name: "ContractSettings", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomApplicationComponent", Members: []string{"*"}},
		{Name: "CustomApplication", Members: []string{"*"}},
		{Name: "CustomField", Members: []string{"*"}},
		{Name: "CustomLabels", Members: []string{"*"}},
		{Name: "CustomMetadata", Members: []string("*")},
		{Name: "CustomObject", Members: stdObjects},
		{Name: "CustomObjectTranslation", Members: []string{"*"}},
		{Name: "CustomPageWebLink", Members: []string{"*"}},
		{Name: "CustomPermission", Members: []string{"*"}},
		{Name: "CustomSite", Members: []string{"*"}},
		{Name: "CustomTab", Members: []string{"*"}},
		{Name: "DataCategoryGroup", Members: []string{"*"}},
		{Name: "EntitlementProcess", Members: []string{"*"}},
		{Name: "EntitlementSettings", Members: []string{"*"}},
		{Name: "EntitlementTemplate", Members: []string{"*"}},
		{Name: "ExternalDataSource", Members: []string{"*"}},
		{Name: "FieldSet", Members: []string{"*"}},
		{Name: "Flow", Members: []string{"*"}},
		{Name: "Folder", Members: []string{"*"}},
		{Name: "ForecastingSettings", Members: []string{"*"}},
		{Name: "Group", Members: []string{"*"}},
		{Name: "HomePageComponent", Members: []string{"*"}},
		{Name: "HomePageLayout", Members: []string{"*"}},
		{Name: "IdeasSettings", Members: []string{"*"}},
		{Name: "KnowledgeSettings", Members: []string{"*"}},
		{Name: "Layout", Members: []string{"*"}},
		{Name: "Letterhead", Members: []string{"*"}},
		{Name: "ListView", Members: []string{"*"}},
		{Name: "LiveAgentSettings", Members: []string{"*"}},
		{Name: "LiveChatAgentConfig", Members: []string{"*"}},
		{Name: "LiveChatButton", Members: []string{"*"}},
		{Name: "LiveChatDeployment", Members: []string{"*"}},
		{Name: "MilestoneType", Members: []string{"*"}},
		{Name: "MobileSettings", Members: []string{"*"}},
		{Name: "NamedFilter", Members: []string{"*"}},
		{Name: "Network", Members: []string{"*"}},
		{Name: "OpportunitySettings", Members: []string{"*"}},
		{Name: "PermissionSet", Members: []string{"*"}},
		{Name: "Portal", Members: []string{"*"}},
		{Name: "PostTemplate", Members: []string{"*"}},
		{Name: "ProductSettings", Members: []string{"*"}},
		{Name: "Profile", Members: []string{"*"}},
		{Name: "Queue", Members: []string{"*"}},
		{Name: "QuickAction", Members: []string{"*"}},
		{Name: "QuoteSettings", Members: []string{"*"}},
		{Name: "RecordType", Members: []string{"*"}},
		{Name: "RemoteSiteSetting", Members: []string{"*"}},
		{Name: "ReportType", Members: []string{"*"}},
		{Name: "Role", Members: []string{"*"}},
		{Name: "SamlSsoConfig", Members: []string{"*"}},
		{Name: "Scontrol", Members: []string{"*"}},
		{Name: "SecuritySettings", Members: []string{"*"}},
		{Name: "SharingReason", Members: []string{"*"}},
		{Name: "SharingRules", Members: []string{"*"}},
		{Name: "Skill", Members: []string{"*"}},
		{Name: "StaticResource", Members: []string{"*"}},
		{Name: "Territory", Members: []string{"*"}},
		{Name: "Translations", Members: []string{"*"}},
		{Name: "ValidationRule", Members: []string{"*"}},
		{Name: "Workflow", Members: []string{"*"}},
	}

	folderResult, _, err := force.Query(fmt.Sprintf("%s", "SELECT Id, Type, DeveloperName from Folder"), false)
	folders := make(map[string]map[string]string)
	for _, folder := range folderResult.Records {
		if folder["DeveloperName"] != nil {
			folderType := folder["Type"].(string)
			m, ok := folders[folderType]
			if !ok {
				m = make(map[string]string)
				folders[folderType] = m
			}
			m[folder["Id"].(string)] = folder["DeveloperName"].(string)
		}
	}
	for foldersType, foldersName := range folders {
		if foldersType == "Email" {
			foldersType = "EmailTemplate"
		}
		members := getMetadataType(foldersType, foldersName)
		query = append(query, ForceMetadataQueryElement{Name: foldersType, Members: members})
	}

	root, err = GetSourceDir()
	if err != nil {
		fmt.Printf("Error obtaining root directory\n")
		ErrorAndExit(err.Error())
	}
	files, err := force.Metadata.Retrieve(query)
	if err != nil {
		fmt.Printf("Encountered and error with retrieve...\n")
		ErrorAndExit(err.Error())
	}
	for name, data := range files {
		file := filepath.Join(root, name)
		dir := filepath.Dir(file)
		if err := os.MkdirAll(dir, 0755); err != nil {
			ErrorAndExit(err.Error())
		}
		if err := ioutil.WriteFile(filepath.Join(root, name), data, 0644); err != nil {
			ErrorAndExit(err.Error())
		}
	}
	fmt.Printf("Exported to %s\n", root)
}
<|endoftext|>