<commit_before>// Package guid provides a GUID type. The backing structure for a GUID is
// identical to that used by the golang.org/x/sys/windows GUID type.
// There are two main binary encodings used for a GUID, the big-endian encoding,
// and the Windows (mixed-endian) encoding. See here for details:
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
package guid

import (
	"crypto/rand"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"github.com/pkg/errors"
	"golang.org/x/sys/windows"
)

// Variant specifies which GUID variant (or "type") of the GUID. It determines
// how the entirety of the rest of the GUID is interpreted.
type Variant uint8

// The variants specified by RFC 4122.
const (
	// VariantUnknown specifies a GUID variant which does not conform to one of
	// the variant encodings specified in RFC 4122.
	VariantUnknown Variant = iota
	VariantNCS
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// Version specifies how the bits in the GUID were generated. For instance, a
// version 4 GUID is randomly generated, and a version 5 is generated from the
// hash of an input string.
type Version uint8

var _ = (json.Marshaler)(GUID{})
var _ = (json.Unmarshaler)(&GUID{})

// GUID represents a GUID/UUID. It has the same structure as
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
// that type. It is defined as its own type so that stringification and
// marshaling can be supported. The representation matches that used by native
// Windows code.
type GUID windows.GUID

// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
func NewV4() (GUID, error) {
	var b [16]byte
	if _, err := rand.Read(b[:]); err != nil {
		return GUID{}, err
	}

	b[6] = (b[6] & 0x0f) | 0x40 // Version 4 (randomly generated)
	b[8] = (b[8] & 0x3f) | 0x80 // RFC4122 variant

	return FromArray(b), nil
}

func fromArray(b [16]byte, order binary.ByteOrder) GUID {
	var g GUID
	g.Data1 = order.Uint32(b[0:4])
	g.Data2 = order.Uint16(b[4:6])
	g.Data3 = order.Uint16(b[6:8])
	copy(g.Data4[:], b[8:16])
	return g
}

func (g GUID) toArray(order binary.ByteOrder) [16]byte {
	b := [16]byte{}
	order.PutUint32(b[0:4], g.Data1)
	order.PutUint16(b[4:6], g.Data2)
	order.PutUint16(b[6:8], g.Data3)
	copy(b[8:16], g.Data4[:])
	return b
}

// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
func FromArray(b [16]byte) GUID {
	return fromArray(b, binary.BigEndian)
}

// ToArray returns an array of 16 bytes representing the GUID in big-endian
// encoding.
func (g GUID) ToArray() [16]byte {
	return g.toArray(binary.BigEndian)
}

// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
func FromWindowsArray(b [16]byte) GUID {
	return fromArray(b, binary.LittleEndian)
}

// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
// encoding.
func (g GUID) ToWindowsArray() [16]byte {
	return g.toArray(binary.LittleEndian)
}

func (g GUID) String() string {
	return fmt.Sprintf(
		"%08x-%04x-%04x-%04x-%012x",
		g.Data1,
		g.Data2,
		g.Data3,
		g.Data4[:2],
		g.Data4[2:])
}

// FromString parses a string containing a GUID and returns the GUID. The only
// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
// format.
func FromString(s string) (GUID, error) {
	if len(s) != 36 {
		return GUID{}, errors.New("invalid GUID format (length)")
	}
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
		return GUID{}, errors.New("invalid GUID format (dashes)")
	}

	var g GUID

	data1, err := strconv.ParseUint(s[0:8], 16, 32)
	if err != nil {
		return GUID{}, errors.Wrap(err, "invalid GUID format (Data1)")
	}
	g.Data1 = uint32(data1)

	data2, err := strconv.ParseUint(s[9:13], 16, 16)
	if err != nil {
		return GUID{}, errors.Wrap(err, "invalid GUID format (Data2)")
	}
	g.Data2 = uint16(data2)

	data3, err := strconv.ParseUint(s[14:18], 16, 16)
	if err != nil {
		return GUID{}, errors.Wrap(err, "invalid GUID format (Data3)")
	}
	g.Data3 = uint16(data3)

	for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
		v, err := strconv.ParseUint(s[x:x+2], 16, 8)
		if err != nil {
			return GUID{}, errors.Wrap(err, "invalid GUID format (Data4)")
		}
		g.Data4[i] = uint8(v)
	}

	return g, nil
}

// Variant returns the GUID variant, as defined in RFC 4122.
func (g GUID) Variant() Variant {
	b := g.Data4[0]
	if b&0x80 == 0 {
		return VariantNCS
	} else if b&0xc0 == 0x80 {
		return VariantRFC4122
	} else if b&0xe0 == 0xc0 {
		return VariantMicrosoft
	} else if b&0xe0 == 0xe0 {
		return VariantFuture
	}
	return VariantUnknown
}

// Version returns the GUID version, as defined in RFC 4122.
func (g GUID) Version() Version {
	return Version((g.Data3 & 0xF000) >> 12)
}

// MarshalJSON marshals the GUID to JSON representation and returns it as a
// slice of bytes.
func (g GUID) MarshalJSON() ([]byte, error) {
	return json.Marshal(g.String())
}

// UnmarshalJSON unmarshals a GUID from JSON representation and sets itself to
// the unmarshaled GUID.
func (g *GUID) UnmarshalJSON(data []byte) error {
	g2, err := FromString(strings.Trim(string(data), "\""))
	if err != nil {
		return err
	}
	*g = g2
	return nil
}
<commit_msg>pkg/guid: Improve error messages<commit_after>// Package guid provides a GUID type. The backing structure for a GUID is
// identical to that used by the golang.org/x/sys/windows GUID type.
// There are two main binary encodings used for a GUID, the big-endian encoding,
// and the Windows (mixed-endian) encoding. See here for details:
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
package guid

import (
	"crypto/rand"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"strconv"
	"strings"

	"golang.org/x/sys/windows"
)

// Variant specifies which GUID variant (or "type") of the GUID. It determines
// how the entirety of the rest of the GUID is interpreted.
type Variant uint8

// The variants specified by RFC 4122.
const (
	// VariantUnknown specifies a GUID variant which does not conform to one of
	// the variant encodings specified in RFC 4122.
	VariantUnknown Variant = iota
	VariantNCS
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// Version specifies how the bits in the GUID were generated. For instance, a
// version 4 GUID is randomly generated, and a version 5 is generated from the
// hash of an input string.
type Version uint8

var _ = (json.Marshaler)(GUID{})
var _ = (json.Unmarshaler)(&GUID{})

// GUID represents a GUID/UUID. It has the same structure as
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
// that type. It is defined as its own type so that stringification and
// marshaling can be supported. The representation matches that used by native
// Windows code.
type GUID windows.GUID

// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
func NewV4() (GUID, error) {
	var b [16]byte
	if _, err := rand.Read(b[:]); err != nil {
		return GUID{}, err
	}

	b[6] = (b[6] & 0x0f) | 0x40 // Version 4 (randomly generated)
	b[8] = (b[8] & 0x3f) | 0x80 // RFC4122 variant

	return FromArray(b), nil
}

func fromArray(b [16]byte, order binary.ByteOrder) GUID {
	var g GUID
	g.Data1 = order.Uint32(b[0:4])
	g.Data2 = order.Uint16(b[4:6])
	g.Data3 = order.Uint16(b[6:8])
	copy(g.Data4[:], b[8:16])
	return g
}

func (g GUID) toArray(order binary.ByteOrder) [16]byte {
	b := [16]byte{}
	order.PutUint32(b[0:4], g.Data1)
	order.PutUint16(b[4:6], g.Data2)
	order.PutUint16(b[6:8], g.Data3)
	copy(b[8:16], g.Data4[:])
	return b
}

// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
func FromArray(b [16]byte) GUID {
	return fromArray(b, binary.BigEndian)
}

// ToArray returns an array of 16 bytes representing the GUID in big-endian
// encoding.
func (g GUID) ToArray() [16]byte {
	return g.toArray(binary.BigEndian)
}

// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
func FromWindowsArray(b [16]byte) GUID {
	return fromArray(b, binary.LittleEndian)
}

// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
// encoding.
func (g GUID) ToWindowsArray() [16]byte {
	return g.toArray(binary.LittleEndian)
}

func (g GUID) String() string {
	return fmt.Sprintf(
		"%08x-%04x-%04x-%04x-%012x",
		g.Data1,
		g.Data2,
		g.Data3,
		g.Data4[:2],
		g.Data4[2:])
}

// FromString parses a string containing a GUID and returns the GUID. The only
// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
// format.
func FromString(s string) (GUID, error) {
	if len(s) != 36 {
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
	}
	if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
	}

	var g GUID

	data1, err := strconv.ParseUint(s[0:8], 16, 32)
	if err != nil {
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
	}
	g.Data1 = uint32(data1)

	data2, err := strconv.ParseUint(s[9:13], 16, 16)
	if err != nil {
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
	}
	g.Data2 = uint16(data2)

	data3, err := strconv.ParseUint(s[14:18], 16, 16)
	if err != nil {
		return GUID{}, fmt.Errorf("invalid GUID %q", s)
	}
	g.Data3 = uint16(data3)

	for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
		v, err := strconv.ParseUint(s[x:x+2], 16, 8)
		if err != nil {
			return GUID{}, fmt.Errorf("invalid GUID %q", s)
		}
		g.Data4[i] = uint8(v)
	}

	return g, nil
}

// Variant returns the GUID variant, as defined in RFC 4122.
func (g GUID) Variant() Variant {
	b := g.Data4[0]
	if b&0x80 == 0 {
		return VariantNCS
	} else if b&0xc0 == 0x80 {
		return VariantRFC4122
	} else if b&0xe0 == 0xc0 {
		return VariantMicrosoft
	} else if b&0xe0 == 0xe0 {
		return VariantFuture
	}
	return VariantUnknown
}

// Version returns the GUID version, as defined in RFC 4122.
func (g GUID) Version() Version {
	return Version((g.Data3 & 0xF000) >> 12)
}

// MarshalJSON marshals the GUID to JSON representation and returns it as a
// slice of bytes.
func (g GUID) MarshalJSON() ([]byte, error) {
	return json.Marshal(g.String())
}

// UnmarshalJSON unmarshals a GUID from JSON representation and sets itself to
// the unmarshaled GUID.
func (g *GUID) UnmarshalJSON(data []byte) error {
	g2, err := FromString(strings.Trim(string(data), "\""))
	if err != nil {
		return err
	}
	*g = g2
	return nil
}
<|endoftext|>


<commit_before>package jobs

import (
	"bytes"
	"encoding/json"
	"time"

	"github.com/cozy/cozy-stack/pkg/utils"
)

const (
	// Queued state
	Queued State = "queued"
	// Running state
	Running = "running"
	// Done state
	Done = "done"
	// Errored state
	Errored = "errored"
)

const (
	// JSONEncoding is a JSON encoding message type
	JSONEncoding = "json"
)

type (
	// Queue interface is used to represent an asynchronous queue of jobs from
	// which it is possible to enqueue and consume jobs.
	Queue interface {
		Enqueue(job Job) error
		Consume() (Job, error)
		Len() int
		Close()
	}

	// Broker interface is used to represent a job broker associated to a
	// particular domain. A broker can be used to create jobs that are pushed in
	// the job system.
	Broker interface {
		Domain() string

		// PushJob will push try to push a new job from the specified job request.
		//
		// This method is asynchronous and returns a chan of JobInfos to observe
		// the job changing states. This channel does not need to be subscribed,
		// messages will be dropped if no listeners.
		PushJob(request *JobRequest) (*JobInfos, <-chan *JobInfos, error)

		// QueueLen returns the total element in the queue of the specified worker
		// type.
		QueueLen(workerType string) (int, error)
	}

	// Job interface represents a job.
	Job interface {
		// Infos returns the JobInfos data associated with the job
		Infos() *JobInfos
		// AckConsumed should be used by the consumer of the job, ack-ing that
		// it has well received the job and is processing it.
		AckConsumed() error
		// Ack should be used by the consumer after the job has been processed,
		// ack-ing that the job was successfully executed.
		Ack() error
		// Nack should be used to tell that the job coult not be consumed or that
		// an error has happened during its processing. The error passed will be
		// used to inform in more detail about the error that happened.
		Nack(error) error
		// Marshal allows you to define how the job should be marshalled when put
		// into the queue.
		Marshal() ([]byte, error)
		// Unmarshal allows you to define how the job should be unmarshalled when
		// consumed from the queue.
		Unmarshal() error
	}

	// State represent the state of a job.
	State string

	// Message is a byte slice representing an encoded job message type.
	Message struct {
		Data []byte
		Type string
	}

	// JobInfos contains all the metadata informations of a Job. It can be
	// marshalled in JSON.
	JobInfos struct {
		ID         string      `json:"id"`
		WorkerType string      `json:"worker_type"`
		Message    *Message    `json:"message"`
		Options    *JobOptions `json:"options"`
		State      State       `json:"state"`
		QueuedAt   time.Time   `json:"queued_at"`
		StartedAt  time.Time   `json:"started_at"`
		Error      error       `json:"error"`
	}

	// JobRequest struct is used to represent a new job request.
	JobRequest struct {
		WorkerType string
		Message    *Message
		Options    *JobOptions
	}

	// JobOptions struct contains the execution properties of the jobs.
	JobOptions struct {
		MaxExecCount uint          `json:"max_exec_count"`
		MaxExecTime  time.Duration `json:"max_exec_time"`
		Timeout      time.Duration `json:"timeout"`
	}

	// WorkerConfig is the configuration parameter of a worker defined by the job
	// system. It contains parameters of the worker along with the worker main
	// function that perform the work against a job's message.
	WorkerConfig struct {
		WorkerFunc   WorkerFunc    `json:"worker_func"`
		Concurrency  uint          `json:"concurrency"`
		MaxExecCount uint          `json:"max_exec_count"`
		MaxExecTime  time.Duration `json:"max_exec_time"`
		Timeout      time.Duration `json:"timeout"`
		RetryDelay   time.Duration `json:"retry_delay"`
	}

	// Scheduler interface is used to represent a scheduler that is responsible
	// to listen respond to triggers jobs requests and send them to the broker.
	Scheduler interface {
		Start(broker Broker) error
		Add(trigger Trigger) error
		Get(id string) (Trigger, error)
		Delete(id string) error
		GetAll() ([]Trigger, error)
	}

	// Trigger interface is used to represent a trigger.
	Trigger interface {
		Type() string
		Infos() *TriggerInfos
		// Schedule should return a channel on which the trigger can send job
		// requests when it decides to.
		Schedule() <-chan *JobRequest
		// Unschedule should be used to clean the trigger states and should close
		// the returns jobs channel.
		Unschedule()
	}

	// TriggerStorage interface is used to represent a persistent layer on which
	// triggers are stored.
	TriggerStorage interface {
		GetAll() ([]Trigger, error)
		Add(trigger Trigger) error
		Delete(trigger Trigger) error
	}

	// TriggerInfos is a struct containing all the options of a trigger.
	TriggerInfos struct {
		ID         string      `json:"_id,omitempty"`
		Rev        string      `json:"_rev,omitempty"`
		Type       string      `json:"type"`
		WorkerType string      `json:"worker"`
		Arguments  string      `json:"arguments"`
		Options    *JobOptions `json:"options"`
		Message    *Message    `json:"message"`
	}

	// TriggerRequest struct contains the paramameters to create a new trigger.
	TriggerRequest struct {
		Type      string          `json:"type"`
		Arguments json.RawMessage `json:"arguments"`
		Options   *WorkerConfig   `json:"options"`
	}
)

// NewTrigger creates the trigger associates with the specified trigger
// options.
func NewTrigger(infos *TriggerInfos) (Trigger, error) {
	switch infos.Type {
	case "@at":
		return NewAtTrigger(infos)
	case "@in":
		return NewInTrigger(infos)
	case "@interval":
		return NewIntervalTrigger(infos)
	default:
		return nil, ErrUnknownTrigger
	}
}

// NewJobInfos creates a new JobInfos instance from a job request.
func NewJobInfos(req *JobRequest) *JobInfos {
	return &JobInfos{
		ID:         utils.RandomString(16),
		WorkerType: req.WorkerType,
		Message:    req.Message,
		Options:    req.Options,
		State:      Queued,
		QueuedAt:   time.Now(),
	}
}

// NewMessage returns a new Message encoded in the specified format.
func NewMessage(enc string, data interface{}) (*Message, error) {
	var b []byte
	var err error
	switch enc {
	case JSONEncoding:
		b, err = json.Marshal(data)
	default:
		err = ErrUnknownMessageType
	}
	if err != nil {
		return nil, err
	}
	return &Message{
		Type: enc,
		Data: b,
	}, nil
}

// Unmarshal can be used to unmarshal the encoded message value in the
// specified interface's type.
func (m *Message) Unmarshal(msg interface{}) error {
	switch m.Type {
	case JSONEncoding:
		return json.NewDecoder(bytes.NewReader(m.Data)).Decode(msg)
	default:
		return ErrUnknownMessageType
	}
}

func (w *WorkerConfig) clone() *WorkerConfig {
	return &WorkerConfig{
		WorkerFunc:   w.WorkerFunc,
		Concurrency:  w.Concurrency,
		MaxExecCount: w.MaxExecCount,
		MaxExecTime:  w.MaxExecTime,
		Timeout:      w.Timeout,
		RetryDelay:   w.RetryDelay,
	}
}
<commit_msg>Remove unused struct<commit_after>package jobs

import (
	"bytes"
	"encoding/json"
	"time"

	"github.com/cozy/cozy-stack/pkg/utils"
)

const (
	// Queued state
	Queued State = "queued"
	// Running state
	Running = "running"
	// Done state
	Done = "done"
	// Errored state
	Errored = "errored"
)

const (
	// JSONEncoding is a JSON encoding message type
	JSONEncoding = "json"
)

type (
	// Queue interface is used to represent an asynchronous queue of jobs from
	// which it is possible to enqueue and consume jobs.
	Queue interface {
		Enqueue(job Job) error
		Consume() (Job, error)
		Len() int
		Close()
	}

	// Broker interface is used to represent a job broker associated to a
	// particular domain. A broker can be used to create jobs that are pushed in
	// the job system.
	Broker interface {
		Domain() string

		// PushJob will push try to push a new job from the specified job request.
		//
		// This method is asynchronous and returns a chan of JobInfos to observe
		// the job changing states. This channel does not need to be subscribed,
		// messages will be dropped if no listeners.
		PushJob(request *JobRequest) (*JobInfos, <-chan *JobInfos, error)

		// QueueLen returns the total element in the queue of the specified worker
		// type.
		QueueLen(workerType string) (int, error)
	}

	// Job interface represents a job.
	Job interface {
		// Infos returns the JobInfos data associated with the job
		Infos() *JobInfos
		// AckConsumed should be used by the consumer of the job, ack-ing that
		// it has well received the job and is processing it.
		AckConsumed() error
		// Ack should be used by the consumer after the job has been processed,
		// ack-ing that the job was successfully executed.
		Ack() error
		// Nack should be used to tell that the job coult not be consumed or that
		// an error has happened during its processing. The error passed will be
		// used to inform in more detail about the error that happened.
		Nack(error) error
		// Marshal allows you to define how the job should be marshalled when put
		// into the queue.
		Marshal() ([]byte, error)
		// Unmarshal allows you to define how the job should be unmarshalled when
		// consumed from the queue.
		Unmarshal() error
	}

	// State represent the state of a job.
	State string

	// Message is a byte slice representing an encoded job message type.
	Message struct {
		Data []byte
		Type string
	}

	// JobInfos contains all the metadata informations of a Job. It can be
	// marshalled in JSON.
	JobInfos struct {
		ID         string      `json:"id"`
		WorkerType string      `json:"worker_type"`
		Message    *Message    `json:"message"`
		Options    *JobOptions `json:"options"`
		State      State       `json:"state"`
		QueuedAt   time.Time   `json:"queued_at"`
		StartedAt  time.Time   `json:"started_at"`
		Error      error       `json:"error"`
	}

	// JobRequest struct is used to represent a new job request.
	JobRequest struct {
		WorkerType string
		Message    *Message
		Options    *JobOptions
	}

	// JobOptions struct contains the execution properties of the jobs.
	JobOptions struct {
		MaxExecCount uint          `json:"max_exec_count"`
		MaxExecTime  time.Duration `json:"max_exec_time"`
		Timeout      time.Duration `json:"timeout"`
	}

	// WorkerConfig is the configuration parameter of a worker defined by the job
	// system. It contains parameters of the worker along with the worker main
	// function that perform the work against a job's message.
	WorkerConfig struct {
		WorkerFunc   WorkerFunc    `json:"worker_func"`
		Concurrency  uint          `json:"concurrency"`
		MaxExecCount uint          `json:"max_exec_count"`
		MaxExecTime  time.Duration `json:"max_exec_time"`
		Timeout      time.Duration `json:"timeout"`
		RetryDelay   time.Duration `json:"retry_delay"`
	}

	// Scheduler interface is used to represent a scheduler that is responsible
	// to listen respond to triggers jobs requests and send them to the broker.
	Scheduler interface {
		Start(broker Broker) error
		Add(trigger Trigger) error
		Get(id string) (Trigger, error)
		Delete(id string) error
		GetAll() ([]Trigger, error)
	}

	// Trigger interface is used to represent a trigger.
	Trigger interface {
		Type() string
		Infos() *TriggerInfos
		// Schedule should return a channel on which the trigger can send job
		// requests when it decides to.
		Schedule() <-chan *JobRequest
		// Unschedule should be used to clean the trigger states and should close
		// the returns jobs channel.
		Unschedule()
	}

	// TriggerStorage interface is used to represent a persistent layer on which
	// triggers are stored.
	TriggerStorage interface {
		GetAll() ([]Trigger, error)
		Add(trigger Trigger) error
		Delete(trigger Trigger) error
	}

	// TriggerInfos is a struct containing all the options of a trigger.
	TriggerInfos struct {
		ID         string      `json:"_id,omitempty"`
		Rev        string      `json:"_rev,omitempty"`
		Type       string      `json:"type"`
		WorkerType string      `json:"worker"`
		Arguments  string      `json:"arguments"`
		Options    *JobOptions `json:"options"`
		Message    *Message    `json:"message"`
	}
)

// NewTrigger creates the trigger associates with the specified trigger
// options.
func NewTrigger(infos *TriggerInfos) (Trigger, error) {
	switch infos.Type {
	case "@at":
		return NewAtTrigger(infos)
	case "@in":
		return NewInTrigger(infos)
	case "@interval":
		return NewIntervalTrigger(infos)
	default:
		return nil, ErrUnknownTrigger
	}
}

// NewJobInfos creates a new JobInfos instance from a job request.
func NewJobInfos(req *JobRequest) *JobInfos {
	return &JobInfos{
		ID:         utils.RandomString(16),
		WorkerType: req.WorkerType,
		Message:    req.Message,
		Options:    req.Options,
		State:      Queued,
		QueuedAt:   time.Now(),
	}
}

// NewMessage returns a new Message encoded in the specified format.
func NewMessage(enc string, data interface{}) (*Message, error) {
	var b []byte
	var err error
	switch enc {
	case JSONEncoding:
		b, err = json.Marshal(data)
	default:
		err = ErrUnknownMessageType
	}
	if err != nil {
		return nil, err
	}
	return &Message{
		Type: enc,
		Data: b,
	}, nil
}

// Unmarshal can be used to unmarshal the encoded message value in the
// specified interface's type.
func (m *Message) Unmarshal(msg interface{}) error {
	switch m.Type {
	case JSONEncoding:
		return json.NewDecoder(bytes.NewReader(m.Data)).Decode(msg)
	default:
		return ErrUnknownMessageType
	}
}

func (w *WorkerConfig) clone() *WorkerConfig {
	return &WorkerConfig{
		WorkerFunc:   w.WorkerFunc,
		Concurrency:  w.Concurrency,
		MaxExecCount: w.MaxExecCount,
		MaxExecTime:  w.MaxExecTime,
		Timeout:      w.Timeout,
		RetryDelay:   w.RetryDelay,
	}
}
<|endoftext|>


<commit_before>package util

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"math/rand"
	"strings"
	"time"

	"github.com/motomux/pretty"
	"k8s.io/client-go/pkg/api/v1"

	"github.com/zalando-incubator/postgres-operator/pkg/spec"
)

const (
	md5prefix = "md5"
)

var passwordChars = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

func init() {
	rand.Seed(int64(time.Now().Unix()))
}

func RandomPassword(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = passwordChars[rand.Intn(len(passwordChars))]
	}

	return string(b)
}

func NameFromMeta(meta v1.ObjectMeta) spec.NamespacedName {
	return spec.NamespacedName{
		Namespace: meta.Namespace,
		Name:      meta.Name,
	}
}

func PGUserPassword(user spec.PgUser) string {
	if (len(user.Password) == md5.Size && user.Password[:3] == md5prefix) || user.Password == "" {
		// Avoid processing already encrypted or empty passwords
		return user.Password
	}
	s := md5.Sum([]byte(user.Password + user.Name))
	return md5prefix + hex.EncodeToString(s[:])
}

func Pretty(x interface{}) (f fmt.Formatter) {
	return pretty.Formatter(x)
}

func PrettyDiff(a, b interface{}) (result string) {
	diff := pretty.Diff(a, b)
	return strings.Join(diff, "\n")
}

func SubstractStringSlices(a []string, b []string) (result []string, equal bool) {
	// Find elements in a that are not in b and return them as a result slice
	// Slices are assumed to contain unique elements only
OUTER:
	for _, vala := range a {
		for _, valb := range b {
			if vala == valb {
				continue OUTER
			}
		}
		result = append(result, vala)
	}
	return result, len(result) == 0
}
<commit_msg>Fix password check in pguserpassword function<commit_after>package util

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"math/rand"
	"strings"
	"time"

	"github.com/motomux/pretty"
	"k8s.io/client-go/pkg/api/v1"

	"github.com/zalando-incubator/postgres-operator/pkg/spec"
)

const (
	md5prefix = "md5"
)

var passwordChars = []byte("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

func init() {
	rand.Seed(int64(time.Now().Unix()))
}

func RandomPassword(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = passwordChars[rand.Intn(len(passwordChars))]
	}

	return string(b)
}

func NameFromMeta(meta v1.ObjectMeta) spec.NamespacedName {
	return spec.NamespacedName{
		Namespace: meta.Namespace,
		Name:      meta.Name,
	}
}

func PGUserPassword(user spec.PgUser) string {
	if (len(user.Password) == md5.Size*2+len(md5prefix) && user.Password[:3] == md5prefix) || user.Password == "" {
		// Avoid processing already encrypted or empty passwords
		return user.Password
	}
	s := md5.Sum([]byte(user.Password + user.Name))
	return md5prefix + hex.EncodeToString(s[:])
}

func Pretty(x interface{}) (f fmt.Formatter) {
	return pretty.Formatter(x)
}

func PrettyDiff(a, b interface{}) (result string) {
	diff := pretty.Diff(a, b)
	return strings.Join(diff, "\n")
}

func SubstractStringSlices(a []string, b []string) (result []string, equal bool) {
	// Find elements in a that are not in b and return them as a result slice
	// Slices are assumed to contain unique elements only
OUTER:
	for _, vala := range a {
		for _, valb := range b {
			if vala == valb {
				continue OUTER
			}
		}
		result = append(result, vala)
	}
	return result, len(result) == 0
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"delay"
	"fmt"
	"rtos"
	"text/linewriter"

	"sdcard"

	"stm32/hal/dma"
	"stm32/hal/exti"
	"stm32/hal/gpio"
	"stm32/hal/irq"
	"stm32/hal/sdmmc"
	"stm32/hal/system"
	"stm32/hal/system/timer/systick"
	"stm32/hal/usart"

	"stm32/hal/raw/pwr"
	"stm32/hal/raw/rcc"
)

var (
	led     gpio.Pin
	sd      *sdmmc.DriverDMA
	tts     *usart.Driver
	bcmRSTn gpio.Pin
	bcmD1   gpio.Pin
)

func init() {
	system.Setup96(26)
	systick.Setup(2e6)

	// GPIO

	gpio.A.EnableClock(false)
	//bcmIRQ := gpio.A.Pin(0)
	tx2 := gpio.A.Pin(2)
	rx2 := gpio.A.Pin(3)
	led = gpio.A.Pin(4)
	bcmCMD := gpio.A.Pin(6)
	//flashMOSI = gpio.A.Pin(7)
	bcmD1 = gpio.A.Pin(8) // Also LSE output (MCO1) to WLAN powersave clock.
	bcmD2 := gpio.A.Pin(9)
	//flashCSn := gpio.A.Pin(15)

	gpio.B.EnableClock(true)
	//flashSCK := gpio.B.Pin(3)
	//flashMISO := gpio.B.Pin(4)
	bcmD3 := gpio.B.Pin(5)
	bcmD0 := gpio.B.Pin(7)
	bcmRSTn = gpio.B.Pin(14)
	bcmCLK := gpio.B.Pin(15)

	// LED

	led.Set()
	led.Setup(&gpio.Config{
		Mode:   gpio.Out,
		Driver: gpio.OpenDrain,
		Speed:  gpio.Low,
	})

	// USART2

	tx2.Setup(&gpio.Config{Mode: gpio.Alt})
	rx2.Setup(&gpio.Config{Mode: gpio.AltIn, Pull: gpio.PullUp})
	tx2.SetAltFunc(gpio.USART2)
	rx2.SetAltFunc(gpio.USART2)
	d := dma.DMA1
	d.EnableClock(true) // DMA clock must remain enabled in sleep mode.
	tts = usart.NewDriver(
		usart.USART2, d.Channel(6, 4), d.Channel(5, 4), make([]byte, 88),
	)
	tts.Periph().EnableClock(true)
	tts.Periph().SetBaudRate(115200)
	tts.Periph().Enable()
	tts.EnableRx()
	tts.EnableTx()
	rtos.IRQ(irq.USART2).Enable()
	rtos.IRQ(irq.DMA1_Stream5).Enable()
	rtos.IRQ(irq.DMA1_Stream6).Enable()
	fmt.DefaultWriter = linewriter.New(
		bufio.NewWriterSize(tts, 88),
		linewriter.CRLF,
	)

	// WLAN (BCM43362: SDIO, reset, IRQ)

	bcmRSTn.Setup(&gpio.Config{Mode: gpio.Out, Speed: gpio.Low})

	cfg := &gpio.Config{Mode: gpio.Alt, Speed: gpio.VeryHigh, Pull: gpio.PullUp}
	for _, pin := range []gpio.Pin{bcmCLK, bcmCMD, bcmD0, bcmD1, bcmD2, bcmD3} {
		pin.Setup(cfg)
		pin.SetAltFunc(gpio.SDIO)
	}
	d = dma.DMA2
	d.EnableClock(true)
	sd = sdmmc.NewDriverDMA(sdmmc.SDIO, d.Channel(6, 4), bcmD0)
	sd.Periph().EnableClock(true)
	sd.Periph().Enable()
	rtos.IRQ(irq.SDIO).Enable()
	rtos.IRQ(irq.EXTI9_5).Enable()
}

func checkErr(what string, err error) {
	if err == nil {
		return
	}
	fmt.Printf("%s: %v\n", what, err)
	for {
		//led.Clear()
		delay.Millisec(100)
		//led.Set()
		delay.Millisec(100)
	}
}

func main() {
	fmt.Printf("Try to communicate with BCM43362:\n")

	// Initialize WLAN

	bcmRSTn.Store(0) // Set WLAN into reset state.

	sd.SetBusWidth(sdcard.Bus1)
	sd.SetClock(400e3, true)

	// Provide WLAN powersave clock on PA8 (SDIO_D1).
	RCC := rcc.RCC
	PWR := pwr.PWR
	RCC.PWREN().Set()
	PWR.DBP().Set()
	RCC.LSEON().Set()
	for RCC.LSERDY().Load() == 0 {
		led.Clear()
		delay.Millisec(50)
		led.Set()
		delay.Millisec(50)
	}
	RCC.MCO1().Store(1 << rcc.MCO1n) // LSE on MCO1.
	PWR.DBP().Clear()
	RCC.PWREN().Clear()
	bcmD1.SetAltFunc(gpio.MCO)

	delay.Millisec(1)
	bcmRSTn.Store(1)

	var (
		rca uint16
		cs  sdcard.CardStatus
	)
	led.Clear()
	for {
		delay.Millisec(1)
		sd.SendCmd(sdcard.CMD0())
		checkErr("CMD0", sd.Err(true))
		sd.SendCmd(sdcard.CMD5(0))
		sd.Err(true)
		rca, cs = sd.SendCmd(sdcard.CMD3()).R6()
		if sd.Err(true) == nil {
			break
		}
	}
	led.Set()
	fmt.Printf("CMD5: rca=%x cs=%s\n", rca, cs)

	cs = sd.SendCmd(sdcard.CMD7(rca)).R1()
	checkErr("CMD7", sd.Err(true))
	fmt.Printf("CMD7: cs=%s\n", cs)

}

func ttsISR() {
	tts.ISR()
}

func ttsRxDMAISR() {
	tts.RxDMAISR()
}

func ttsTxDMAISR() {
	tts.TxDMAISR()
}

func sdioISR() {
	sd.ISR()
}

func exti9_5ISR() {
	pending := exti.Pending() & 0x3E0
	pending.ClearPending()
	if pending&sd.BusyLine() != 0 {
		sd.BusyISR()
	}
}

//c:__attribute__((section(".ISRs")))
var ISRs = [...]func(){
	irq.USART2:       ttsISR,
	irq.DMA1_Stream5: ttsRxDMAISR,
	irq.DMA1_Stream6: ttsTxDMAISR,

	irq.SDIO:    sdioISR,
	irq.EXTI9_5: exti9_5ISR,
}
<commit_msg>examples/wifimcu/bcm43362: Next init command.<commit_after>package main

import (
	"bufio"
	"delay"
	"fmt"
	"rtos"
	"text/linewriter"

	"sdcard"
	"sdcard/sdio"

	"stm32/hal/dma"
	"stm32/hal/exti"
	"stm32/hal/gpio"
	"stm32/hal/irq"
	"stm32/hal/sdmmc"
	"stm32/hal/system"
	"stm32/hal/system/timer/systick"
	"stm32/hal/usart"

	"stm32/hal/raw/pwr"
	"stm32/hal/raw/rcc"
)

var (
	led     gpio.Pin
	sd      *sdmmc.DriverDMA
	tts     *usart.Driver
	bcmRSTn gpio.Pin
	bcmD1   gpio.Pin
)

func init() {
	system.Setup96(26)
	systick.Setup(2e6)

	// GPIO

	gpio.A.EnableClock(false)
	//bcmIRQ := gpio.A.Pin(0)
	tx2 := gpio.A.Pin(2)
	rx2 := gpio.A.Pin(3)
	led = gpio.A.Pin(4)
	bcmCMD := gpio.A.Pin(6)
	//flashMOSI = gpio.A.Pin(7)
	bcmD1 = gpio.A.Pin(8) // Also LSE output (MCO1) to WLAN powersave clock.
	bcmD2 := gpio.A.Pin(9)
	//flashCSn := gpio.A.Pin(15)

	gpio.B.EnableClock(true)
	//flashSCK := gpio.B.Pin(3)
	//flashMISO := gpio.B.Pin(4)
	bcmD3 := gpio.B.Pin(5)
	bcmD0 := gpio.B.Pin(7)
	bcmRSTn = gpio.B.Pin(14)
	bcmCLK := gpio.B.Pin(15)

	// LED

	led.Set()
	led.Setup(&gpio.Config{
		Mode:   gpio.Out,
		Driver: gpio.OpenDrain,
		Speed:  gpio.Low,
	})

	// USART2

	tx2.Setup(&gpio.Config{Mode: gpio.Alt})
	rx2.Setup(&gpio.Config{Mode: gpio.AltIn, Pull: gpio.PullUp})
	tx2.SetAltFunc(gpio.USART2)
	rx2.SetAltFunc(gpio.USART2)
	d := dma.DMA1
	d.EnableClock(true) // DMA clock must remain enabled in sleep mode.
	tts = usart.NewDriver(
		usart.USART2, d.Channel(6, 4), d.Channel(5, 4), make([]byte, 88),
	)
	tts.Periph().EnableClock(true)
	tts.Periph().SetBaudRate(115200)
	tts.Periph().Enable()
	tts.EnableRx()
	tts.EnableTx()
	rtos.IRQ(irq.USART2).Enable()
	rtos.IRQ(irq.DMA1_Stream5).Enable()
	rtos.IRQ(irq.DMA1_Stream6).Enable()
	fmt.DefaultWriter = linewriter.New(
		bufio.NewWriterSize(tts, 88),
		linewriter.CRLF,
	)

	// WLAN (BCM43362: SDIO, reset, IRQ)

	bcmRSTn.Setup(&gpio.Config{Mode: gpio.Out, Speed: gpio.Low})

	cfg := &gpio.Config{Mode: gpio.Alt, Speed: gpio.VeryHigh, Pull: gpio.PullUp}
	for _, pin := range []gpio.Pin{bcmCLK, bcmCMD, bcmD0, bcmD1, bcmD2, bcmD3} {
		pin.Setup(cfg)
		pin.SetAltFunc(gpio.SDIO)
	}
	d = dma.DMA2
	d.EnableClock(true)
	sd = sdmmc.NewDriverDMA(sdmmc.SDIO, d.Channel(6, 4), bcmD0)
	sd.Periph().EnableClock(true)
	sd.Periph().Enable()
	rtos.IRQ(irq.SDIO).Enable()
	rtos.IRQ(irq.EXTI9_5).Enable()
}

func checkErr(what string, err error) {
	if err == nil {
		return
	}
	fmt.Printf("%s: %v\n", what, err)
	for {
		//led.Clear()
		delay.Millisec(100)
		//led.Set()
		delay.Millisec(100)
	}
}

func main() {
	fmt.Printf("Try to communicate with BCM43362:\n")

	// Initialize WLAN

	bcmRSTn.Store(0) // Set WLAN into reset state.

	sd.SetBusWidth(sdcard.Bus1)
	sd.SetClock(400e3, true)

	// Provide WLAN powersave clock on PA8 (SDIO_D1).
	RCC := rcc.RCC
	PWR := pwr.PWR
	RCC.PWREN().Set()
	PWR.DBP().Set()
	RCC.LSEON().Set()
	for RCC.LSERDY().Load() == 0 {
		led.Clear()
		delay.Millisec(50)
		led.Set()
		delay.Millisec(50)
	}
	RCC.MCO1().Store(1 << rcc.MCO1n) // LSE on MCO1.
	PWR.DBP().Clear()
	RCC.PWREN().Clear()
	bcmD1.SetAltFunc(gpio.MCO)

	delay.Millisec(1)
	bcmRSTn.Store(1)

	var (
		rca uint16
		cs  sdcard.CardStatus
	)
	led.Clear()
	for {
		delay.Millisec(1)
		sd.SendCmd(sdcard.CMD0())
		checkErr("CMD0", sd.Err(true))
		sd.SendCmd(sdcard.CMD5(0))
		sd.Err(true)
		rca, cs = sd.SendCmd(sdcard.CMD3()).R6()
		if sd.Err(true) == nil {
			break
		}
	}
	led.Set()
	fmt.Printf("CMD5: rca=%x cs=%s\n", rca, cs)

	cs = sd.SendCmd(sdcard.CMD7(rca)).R1()
	checkErr("CMD7", sd.Err(true))
	fmt.Printf("CMD7: cs=%s\n", cs)

	fmt.Printf("Enable FN1: ")
	for {
		ioen, st := sd.SendCmd(sdcard.CMD52(
			sdio.CIA, sdio.CCCR_IOEN, sdcard.Write|sdcard.RAW, sdio.FN1,
		)).R5()
		checkErr("CMD52", sd.Err(true))
		if st&^sdcard.IO_CURRENT_STATE != 0 {
			fmt.Println(st)
			return
		}
		if ioen&sdio.FN1 != 0 {
			break
		}
		delay.Millisec(1)
	}
	fmt.Printf("OK\n")
}

func ttsISR() {
	tts.ISR()
}

func ttsRxDMAISR() {
	tts.RxDMAISR()
}

func ttsTxDMAISR() {
	tts.TxDMAISR()
}

func sdioISR() {
	sd.ISR()
}

func exti9_5ISR() {
	pending := exti.Pending() & 0x3E0
	pending.ClearPending()
	if pending&sd.BusyLine() != 0 {
		sd.BusyISR()
	}
}

//c:__attribute__((section(".ISRs")))
var ISRs = [...]func(){
	irq.USART2:       ttsISR,
	irq.DMA1_Stream5: ttsRxDMAISR,
	irq.DMA1_Stream6: ttsTxDMAISR,

	irq.SDIO:    sdioISR,
	irq.EXTI9_5: exti9_5ISR,
}
<|endoftext|>


<commit_before>package main

import "time"

type LEDController struct {
	LightConf
	led    *LED
	state  bool
	schedC chan Schedule
	done   chan struct{}
}

func NewLEDController(lc LightConf) (*LEDController, error) {
	led, err := NewLED(lc.Pin)
	if err != nil {
		return nil, err
	}

	c := &LEDController{
		LightConf: lc,
		led:       led,
		schedC:    make(chan Schedule),
		done:      make(chan struct{}),
	}
	go c.run()
	c.schedC <- lc.Schedule

	return c, nil
}

func (s *LEDController) UpdateSchedule(sched Schedule) {
	s.schedC <- sched
}

func (s *LEDController) run() {
	err := s.led.Off()
	if err != nil {
		panic(err)
	}
	var sched Schedule
	t := time.NewTimer(sched.NextTick())
	for {
		select {
		case <-t.C:
			err := s.led.Set(sched.CurrentState())
			if err != nil {
				panic(err)
			}
			t.Reset(sched.NextTick())

		case sched = <-s.schedC:
			t.Reset(10 * time.Millisecond)
		case <-s.done:
			t.Stop()
			s.led.Close()
			return
		case s.schedC <- sched:

		}
	}
}

func (s *LEDController) Close() error {
	close(s.done)
	return nil
}

const (
	ScheduleTicks = 48
	day           = 24 * time.Hour
	durPrTick     = day / ScheduleTicks
)

// 30 minute interval
type Schedule [ScheduleTicks]LEDState

func (s Schedule) State(t time.Time) LEDState {
	return s[stateIdx(t)]
}

func (s Schedule) CurrentState() LEDState {
	return s.State(time.Now())
}

// NextTick returns the time until the next tick is to happen.
func (s Schedule) NextTick() time.Duration {
	now := stateIdx(time.Now())
	return timeTill(now, now+1)
}

func stateIdx(t time.Time) int {

	t = t.Round(durPrTick)

	a := time.Duration(t.Hour()) * time.Hour
	a += time.Duration(t.Minute()) * time.Minute
	a += time.Duration(t.Second()) * time.Second

	return int(a / durPrTick)
}

func timeTill(from, to int) time.Duration {
	if from >= ScheduleTicks {
		from %= ScheduleTicks
	}
	if to >= ScheduleTicks {
		to %= ScheduleTicks
	}

	// switch it around
	if to < from {
		from, to = to, from
	}

	return time.Duration((to - from)) * durPrTick
}
<commit_msg>let's not round off here<commit_after>package main

import "time"

type LEDController struct {
	LightConf
	led    *LED
	state  bool
	schedC chan Schedule
	done   chan struct{}
}

func NewLEDController(lc LightConf) (*LEDController, error) {
	led, err := NewLED(lc.Pin)
	if err != nil {
		return nil, err
	}

	c := &LEDController{
		LightConf: lc,
		led:       led,
		schedC:    make(chan Schedule),
		done:      make(chan struct{}),
	}
	go c.run()
	c.schedC <- lc.Schedule

	return c, nil
}

func (s *LEDController) UpdateSchedule(sched Schedule) {
	s.schedC <- sched
}

func (s *LEDController) run() {
	err := s.led.Off()
	if err != nil {
		panic(err)
	}
	var sched Schedule
	t := time.NewTimer(sched.NextTick())
	for {
		select {
		case <-t.C:
			err := s.led.Set(sched.CurrentState())
			if err != nil {
				panic(err)
			}
			t.Reset(sched.NextTick())

		case sched = <-s.schedC:
			t.Reset(10 * time.Millisecond)
		case <-s.done:
			t.Stop()
			s.led.Close()
			return
		case s.schedC <- sched:

		}
	}
}

func (s *LEDController) Close() error {
	close(s.done)
	return nil
}

const (
	ScheduleTicks = 48
	day           = 24 * time.Hour
	durPrTick     = day / ScheduleTicks
)

// 30 minute interval
type Schedule [ScheduleTicks]LEDState

func (s Schedule) State(t time.Time) LEDState {
	return s[stateIdx(t)]
}

func (s Schedule) CurrentState() LEDState {
	return s.State(time.Now())
}

// NextTick returns the time until the next tick is to happen.
func (s Schedule) NextTick() time.Duration {
	now := stateIdx(time.Now())
	return timeTill(now, now+1)
}

func stateIdx(t time.Time) int {

	a := time.Duration(t.Hour()) * time.Hour
	a += time.Duration(t.Minute()) * time.Minute
	a += time.Duration(t.Second()) * time.Second

	return int(a / durPrTick)
}

func timeTill(from, to int) time.Duration {
	if from >= ScheduleTicks {
		from %= ScheduleTicks
	}
	if to >= ScheduleTicks {
		to %= ScheduleTicks
	}

	// switch it around
	if to < from {
		from, to = to, from
	}

	return time.Duration((to - from)) * durPrTick
}
<|endoftext|>


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

package main

import (
	"go/ast"
)

func init() {
	register(go1pkgrenameFix)
}

var go1pkgrenameFix = fix{
	"go1rename",
	"2011-11-08",
	go1pkgrename,
	`Rewrite imports for packages moved during transition to Go 1.

http://codereview.appspot.com/5316078
`,
}

var go1PackageRenames = []struct{ old, new string }{
	{"asn1", "encoding/asn1"},
	{"big", "math/big"},
	{"cmath", "math/cmplx"},
	{"csv", "encoding/csv"},
	{"exec", "os/exec"},
	{"exp/template/html", "html/template"},
	{"gob", "encoding/gob"},
	{"http", "net/http"},
	{"http/cgi", "net/http/cgi"},
	{"http/fcgi", "net/http/fcgi"},
	{"http/httptest", "net/http/httptest"},
	{"http/pprof", "net/http/pprof"},
	{"json", "encoding/json"},
	{"mail", "net/mail"},
	{"rpc", "net/rpc"},
	{"rpc/jsonrpc", "net/rpc/jsonrpc"},
	{"scanner", "text/scanner"},
	{"smtp", "net/smtp"},
	{"syslog", "log/syslog"},
	{"tabwriter", "text/tabwriter"},
	{"template", "text/template"},
	{"template/parse", "text/template/parse"},
	{"rand", "math/rand"},
	{"url", "net/url"},
	{"utf16", "unicode/utf16"},
	{"utf8", "unicode/utf8"},
	{"xml", "encoding/xml"},

	// go.crypto sub-repository
	{"crypto/bcrypt", "code.google.com/p/go.crypto/bcrypt"},
	{"crypto/blowfish", "code.google.com/p/go.crypto/blowfish"},
	{"crypto/cast5", "code.google.com/p/go.crypto/cast5"},
	{"crypto/md4", "code.google.com/p/go.crypto/md4"},
	{"crypto/ocsp", "code.google.com/p/go.crypto/ocsp"},
	{"crypto/openpgp", "code.google.com/p/go.crypto/openpgp"},
	{"crypto/openpgp/armor", "code.google.com/p/go.crypto/openpgp/armor"},
	{"crypto/openpgp/elgamal", "code.google.com/p/go.crypto/openpgp/elgamal"},
	{"crypto/openpgp/errors", "code.google.com/p/go.crypto/openpgp/errors"},
	{"crypto/openpgp/packet", "code.google.com/p/go.crypto/openpgp/packet"},
	{"crypto/openpgp/s2k", "code.google.com/p/go.crypto/openpgp/s2k"},
	{"crypto/ripemd160", "code.google.com/p/go.crypto/ripemd160"},
	{"crypto/twofish", "code.google.com/p/go.crypto/twofish"},
	{"crypto/xtea", "code.google.com/p/go.crypto/xtea"},
	{"exp/ssh", "code.google.com/p/go.crypto/ssh"},

	// go.net sub-repository
	{"net/dict", "code.google.com/p/go.net/dict"},
	{"net/websocket", "code.google.com/p/go.net/websocket"},
	{"exp/spdy", "code.google.com/p/go.net/spdy"},

	// go.codereview sub-repository
	{"encoding/git85", "code.google.com/p/go.codereview/git85"},
	{"patch", "code.google.com/p/go.codereview/patch"},
}

var go1PackageNameRenames = []struct{ newPath, old, new string }{
	{"html/template", "html", "template"},
	{"math/cmplx", "cmath", "cmplx"},
}

func go1pkgrename(f *ast.File) bool {
	fixed := false

	// First update the imports.
	for _, rename := range go1PackageRenames {
		if !imports(f, rename.old) {
			continue
		}
		if rewriteImport(f, rename.old, rename.new) {
			fixed = true
		}
	}
	if !fixed {
		return false
	}

	// Now update the package names used by importers.
	for _, rename := range go1PackageNameRenames {
		// These are rare packages, so do the import test before walking.
		if imports(f, rename.newPath) {
			walk(f, func(n interface{}) {
				if sel, ok := n.(*ast.SelectorExpr); ok {
					if isTopName(sel.X, rename.old) {
						// We know Sel.X is an Ident.
						sel.X.(*ast.Ident).Name = rename.new
						return
					}
				}
			})
		}
	}

	return fixed
}
<commit_msg>fix: add image/{bmp,tiff} to go1pkgrename.<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"go/ast"
)

func init() {
	register(go1pkgrenameFix)
}

var go1pkgrenameFix = fix{
	"go1rename",
	"2011-11-08",
	go1pkgrename,
	`Rewrite imports for packages moved during transition to Go 1.

http://codereview.appspot.com/5316078
`,
}

var go1PackageRenames = []struct{ old, new string }{
	{"asn1", "encoding/asn1"},
	{"big", "math/big"},
	{"cmath", "math/cmplx"},
	{"csv", "encoding/csv"},
	{"exec", "os/exec"},
	{"exp/template/html", "html/template"},
	{"gob", "encoding/gob"},
	{"http", "net/http"},
	{"http/cgi", "net/http/cgi"},
	{"http/fcgi", "net/http/fcgi"},
	{"http/httptest", "net/http/httptest"},
	{"http/pprof", "net/http/pprof"},
	{"json", "encoding/json"},
	{"mail", "net/mail"},
	{"rpc", "net/rpc"},
	{"rpc/jsonrpc", "net/rpc/jsonrpc"},
	{"scanner", "text/scanner"},
	{"smtp", "net/smtp"},
	{"syslog", "log/syslog"},
	{"tabwriter", "text/tabwriter"},
	{"template", "text/template"},
	{"template/parse", "text/template/parse"},
	{"rand", "math/rand"},
	{"url", "net/url"},
	{"utf16", "unicode/utf16"},
	{"utf8", "unicode/utf8"},
	{"xml", "encoding/xml"},

	// go.crypto sub-repository
	{"crypto/bcrypt", "code.google.com/p/go.crypto/bcrypt"},
	{"crypto/blowfish", "code.google.com/p/go.crypto/blowfish"},
	{"crypto/cast5", "code.google.com/p/go.crypto/cast5"},
	{"crypto/md4", "code.google.com/p/go.crypto/md4"},
	{"crypto/ocsp", "code.google.com/p/go.crypto/ocsp"},
	{"crypto/openpgp", "code.google.com/p/go.crypto/openpgp"},
	{"crypto/openpgp/armor", "code.google.com/p/go.crypto/openpgp/armor"},
	{"crypto/openpgp/elgamal", "code.google.com/p/go.crypto/openpgp/elgamal"},
	{"crypto/openpgp/errors", "code.google.com/p/go.crypto/openpgp/errors"},
	{"crypto/openpgp/packet", "code.google.com/p/go.crypto/openpgp/packet"},
	{"crypto/openpgp/s2k", "code.google.com/p/go.crypto/openpgp/s2k"},
	{"crypto/ripemd160", "code.google.com/p/go.crypto/ripemd160"},
	{"crypto/twofish", "code.google.com/p/go.crypto/twofish"},
	{"crypto/xtea", "code.google.com/p/go.crypto/xtea"},
	{"exp/ssh", "code.google.com/p/go.crypto/ssh"},

	// go.image sub-repository
	{"image/bmp", "code.google.com/p/go.image/bmp"},
	{"image/tiff", "code.google.com/p/go.image/tiff"},

	// go.net sub-repository
	{"net/dict", "code.google.com/p/go.net/dict"},
	{"net/websocket", "code.google.com/p/go.net/websocket"},
	{"exp/spdy", "code.google.com/p/go.net/spdy"},

	// go.codereview sub-repository
	{"encoding/git85", "code.google.com/p/go.codereview/git85"},
	{"patch", "code.google.com/p/go.codereview/patch"},
}

var go1PackageNameRenames = []struct{ newPath, old, new string }{
	{"html/template", "html", "template"},
	{"math/cmplx", "cmath", "cmplx"},
}

func go1pkgrename(f *ast.File) bool {
	fixed := false

	// First update the imports.
	for _, rename := range go1PackageRenames {
		if !imports(f, rename.old) {
			continue
		}
		if rewriteImport(f, rename.old, rename.new) {
			fixed = true
		}
	}
	if !fixed {
		return false
	}

	// Now update the package names used by importers.
	for _, rename := range go1PackageNameRenames {
		// These are rare packages, so do the import test before walking.
		if imports(f, rename.newPath) {
			walk(f, func(n interface{}) {
				if sel, ok := n.(*ast.SelectorExpr); ok {
					if isTopName(sel.X, rename.old) {
						// We know Sel.X is an Ident.
						sel.X.(*ast.Ident).Name = rename.new
						return
					}
				}
			})
		}
	}

	return fixed
}
<|endoftext|>


<commit_before>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package serializer

import (
	"mime"
	"strings"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
	"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
	"k8s.io/apimachinery/pkg/runtime/serializer/versioning"
)

// serializerExtensions are for serializers that are conditionally compiled in
var serializerExtensions = []func(*runtime.Scheme) (serializerType, bool){}

type serializerType struct {
	AcceptContentTypes []string
	ContentType        string
	FileExtensions     []string
	// EncodesAsText should be true if this content type can be represented safely in UTF-8
	EncodesAsText bool

	Serializer       runtime.Serializer
	PrettySerializer runtime.Serializer

	AcceptStreamContentTypes []string
	StreamContentType        string

	Framer           runtime.Framer
	StreamSerializer runtime.Serializer
}

func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType {
	jsonSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},
	)
	jsonSerializerType := serializerType{
		AcceptContentTypes: []string{runtime.ContentTypeJSON},
		ContentType:        runtime.ContentTypeJSON,
		FileExtensions:     []string{"json"},
		EncodesAsText:      true,
		Serializer:         jsonSerializer,

		Framer:           json.Framer,
		StreamSerializer: jsonSerializer,
	}
	if options.Pretty {
		jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions(
			mf, scheme, scheme,
			json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict},
		)
	}

	yamlSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict},
	)
	protoSerializer := protobuf.NewSerializer(scheme, scheme)
	protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)

	serializers := []serializerType{
		jsonSerializerType,
		{
			AcceptContentTypes: []string{runtime.ContentTypeYAML},
			ContentType:        runtime.ContentTypeYAML,
			FileExtensions:     []string{"yaml"},
			EncodesAsText:      true,
			Serializer:         yamlSerializer,
		},
		{
			AcceptContentTypes: []string{runtime.ContentTypeProtobuf},
			ContentType:        runtime.ContentTypeProtobuf,
			FileExtensions:     []string{"pb"},
			Serializer:         protoSerializer,

			Framer:           protobuf.LengthDelimitedFramer,
			StreamSerializer: protoRawSerializer,
		},
	}

	for _, fn := range serializerExtensions {
		if serializer, ok := fn(scheme); ok {
			serializers = append(serializers, serializer)
		}
	}
	return serializers
}

// CodecFactory provides methods for retrieving codecs and serializers for specific
// versions and content types.
type CodecFactory struct {
	scheme      *runtime.Scheme
	serializers []serializerType
	universal   runtime.Decoder
	accepts     []runtime.SerializerInfo

	legacySerializer runtime.Serializer
}

// CodecFactoryOptions holds the options for configuring CodecFactory behavior
type CodecFactoryOptions struct {
	// Strict configures all serializers in strict mode
	Strict bool
	// Pretty includes a pretty serializer along with the non-pretty one
	Pretty bool
}

// CodecFactoryOptionsMutator takes a pointer to an options struct and then modifies it.
// Functions implementing this type can be passed to the NewCodecFactory() constructor.
type CodecFactoryOptionsMutator func(*CodecFactoryOptions)

// EnablePretty enables including a pretty serializer along with the non-pretty one
func EnablePretty(options *CodecFactoryOptions) {
	options.Pretty = true
}

// DisablePretty disables including a pretty serializer along with the non-pretty one
func DisablePretty(options *CodecFactoryOptions) {
	options.Pretty = false
}

// EnableStrict enables configuring all serializers in strict mode
func EnableStrict(options *CodecFactoryOptions) {
	options.Strict = true
}

// DisableStrict disables configuring all serializers in strict mode
func DisableStrict(options *CodecFactoryOptions) {
	options.Strict = false
}

// NewCodecFactory provides methods for retrieving serializers for the supported wire formats
// and conversion wrappers to define preferred internal and external versions. In the future,
// as the internal version is used less, callers may instead use a defaulting serializer and
// only convert objects which are shared internally (Status, common API machinery).
//
// Mutators can be passed to change the CodecFactoryOptions before construction of the factory.
// It is recommended to explicitly pass mutators instead of relying on defaults.
// By default, Pretty is enabled -- this is conformant with previously supported behavior.
//
// TODO: allow other codecs to be compiled in?
// TODO: accept a scheme interface
func NewCodecFactory(scheme *runtime.Scheme, mutators ...CodecFactoryOptionsMutator) CodecFactory {
	options := CodecFactoryOptions{Pretty: true}
	for _, fn := range mutators {
		fn(&options)
	}

	serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory, options)
	return newCodecFactory(scheme, serializers)
}

// newCodecFactory is a helper for testing that allows a different metafactory to be specified.
func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) CodecFactory {
	decoders := make([]runtime.Decoder, 0, len(serializers))
	var accepts []runtime.SerializerInfo
	alreadyAccepted := make(map[string]struct{})

	var legacySerializer runtime.Serializer
	for _, d := range serializers {
		decoders = append(decoders, d.Serializer)
		for _, mediaType := range d.AcceptContentTypes {
			if _, ok := alreadyAccepted[mediaType]; ok {
				continue
			}
			alreadyAccepted[mediaType] = struct{}{}
			info := runtime.SerializerInfo{
				MediaType:        d.ContentType,
				EncodesAsText:    d.EncodesAsText,
				Serializer:       d.Serializer,
				PrettySerializer: d.PrettySerializer,
			}

			mediaType, _, err := mime.ParseMediaType(info.MediaType)
			if err != nil {
				panic(err)
			}
			parts := strings.SplitN(mediaType, "/", 2)
			info.MediaTypeType = parts[0]
			info.MediaTypeSubType = parts[1]

			if d.StreamSerializer != nil {
				info.StreamSerializer = &runtime.StreamSerializerInfo{
					Serializer:    d.StreamSerializer,
					EncodesAsText: d.EncodesAsText,
					Framer:        d.Framer,
				}
			}
			accepts = append(accepts, info)
			if mediaType == runtime.ContentTypeJSON {
				legacySerializer = d.Serializer
			}
		}
	}
	if legacySerializer == nil {
		legacySerializer = serializers[0].Serializer
	}

	return CodecFactory{
		scheme:      scheme,
		serializers: serializers,
		universal:   recognizer.NewDecoder(decoders...),

		accepts: accepts,

		legacySerializer: legacySerializer,
	}
}

// WithoutConversion returns a NegotiatedSerializer that performs no conversion, even if the
// caller requests it.
func (f CodecFactory) WithoutConversion() runtime.NegotiatedSerializer {
	return WithoutConversionCodecFactory{f}
}

// SupportedMediaTypes returns the RFC2046 media types that this factory has serializers for.
func (f CodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
	return f.accepts
}

// LegacyCodec encodes output to a given API versions, and decodes output into the internal form from
// any recognized source. The returned codec will always encode output to JSON. If a type is not
// found in the list of versions an error will be returned.
//
// This method is deprecated - clients and servers should negotiate a serializer by mime-type and
// invoke CodecForVersions. Callers that need only to read data should use UniversalDecoder().
//
// TODO: make this call exist only in pkg/api, and initialize it with the set of default versions.
//   All other callers will be forced to request a Codec directly.
func (f CodecFactory) LegacyCodec(version ...schema.GroupVersion) runtime.Codec {
	return versioning.NewDefaultingCodecForScheme(f.scheme, f.legacySerializer, f.universal, schema.GroupVersions(version), runtime.InternalGroupVersioner)
}

// UniversalDeserializer can convert any stored data recognized by this factory into a Go object that satisfies
// runtime.Object. It does not perform conversion. It does not perform defaulting.
func (f CodecFactory) UniversalDeserializer() runtime.Decoder {
	return f.universal
}

// UniversalDecoder returns a runtime.Decoder capable of decoding all known API objects in all known formats. Used
// by clients that do not need to encode objects but want to deserialize API objects stored on disk. Only decodes
// objects in groups registered with the scheme. The GroupVersions passed may be used to select alternate
// versions of objects to return - by default, runtime.APIVersionInternal is used. If any versions are specified,
// unrecognized groups will be returned in the version they are encoded as (no conversion). This decoder performs
// defaulting.
//
// TODO: the decoder will eventually be removed in favor of dealing with objects in their versioned form
// TODO: only accept a group versioner
func (f CodecFactory) UniversalDecoder(versions ...schema.GroupVersion) runtime.Decoder {
	var versioner runtime.GroupVersioner
	if len(versions) == 0 {
		versioner = runtime.InternalGroupVersioner
	} else {
		versioner = schema.GroupVersions(versions)
	}
	return f.CodecForVersions(nil, f.universal, nil, versioner)
}

// CodecForVersions creates a codec with the provided serializer. If an object is decoded and its group is not in the list,
// it will default to runtime.APIVersionInternal. If encode is not specified for an object's group, the object is not
// converted. If encode or decode are nil, no conversion is performed.
func (f CodecFactory) CodecForVersions(encoder runtime.Encoder, decoder runtime.Decoder, encode runtime.GroupVersioner, decode runtime.GroupVersioner) runtime.Codec {
	// TODO: these are for backcompat, remove them in the future
	if encode == nil {
		encode = runtime.DisabledGroupVersioner
	}
	if decode == nil {
		decode = runtime.InternalGroupVersioner
	}
	return versioning.NewDefaultingCodecForScheme(f.scheme, encoder, decoder, encode, decode)
}

// DecoderToVersion returns a decoder that targets the provided group version.
func (f CodecFactory) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
	return f.CodecForVersions(nil, decoder, nil, gv)
}

// EncoderForVersion returns an encoder that targets the provided group version.
func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
	return f.CodecForVersions(encoder, nil, gv, nil)
}

// WithoutConversionCodecFactory is a CodecFactory that will explicitly ignore requests to perform conversion.
// This wrapper is used while code migrates away from using conversion (such as external clients) and in the future
// will be unnecessary when we change the signature of NegotiatedSerializer.
type WithoutConversionCodecFactory struct {
	CodecFactory
}

// EncoderForVersion returns an encoder that does not do conversion, but does set the group version kind of the object
// when serialized.
func (f WithoutConversionCodecFactory) EncoderForVersion(serializer runtime.Encoder, version runtime.GroupVersioner) runtime.Encoder {
	return runtime.WithVersionEncoder{
		Version:     version,
		Encoder:     serializer,
		ObjectTyper: f.CodecFactory.scheme,
	}
}

// DecoderToVersion returns an decoder that does not do conversion.
func (f WithoutConversionCodecFactory) DecoderToVersion(serializer runtime.Decoder, _ runtime.GroupVersioner) runtime.Decoder {
	return runtime.WithoutVersionDecoder{
		Decoder: serializer,
	}
}

// DirectCodecFactory was renamed to WithoutConversionCodecFactory in 1.15.
// TODO: remove in 1.16.
type DirectCodecFactory = WithoutConversionCodecFactory
<commit_msg>feat: remove several types in runtime serializer<commit_after>/*
Copyright 2014 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package serializer

import (
	"mime"
	"strings"

	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
	"k8s.io/apimachinery/pkg/runtime/serializer/recognizer"
	"k8s.io/apimachinery/pkg/runtime/serializer/versioning"
)

// serializerExtensions are for serializers that are conditionally compiled in
var serializerExtensions = []func(*runtime.Scheme) (serializerType, bool){}

type serializerType struct {
	AcceptContentTypes []string
	ContentType        string
	FileExtensions     []string
	// EncodesAsText should be true if this content type can be represented safely in UTF-8
	EncodesAsText bool

	Serializer       runtime.Serializer
	PrettySerializer runtime.Serializer

	AcceptStreamContentTypes []string
	StreamContentType        string

	Framer           runtime.Framer
	StreamSerializer runtime.Serializer
}

func newSerializersForScheme(scheme *runtime.Scheme, mf json.MetaFactory, options CodecFactoryOptions) []serializerType {
	jsonSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: false, Pretty: false, Strict: options.Strict},
	)
	jsonSerializerType := serializerType{
		AcceptContentTypes: []string{runtime.ContentTypeJSON},
		ContentType:        runtime.ContentTypeJSON,
		FileExtensions:     []string{"json"},
		EncodesAsText:      true,
		Serializer:         jsonSerializer,

		Framer:           json.Framer,
		StreamSerializer: jsonSerializer,
	}
	if options.Pretty {
		jsonSerializerType.PrettySerializer = json.NewSerializerWithOptions(
			mf, scheme, scheme,
			json.SerializerOptions{Yaml: false, Pretty: true, Strict: options.Strict},
		)
	}

	yamlSerializer := json.NewSerializerWithOptions(
		mf, scheme, scheme,
		json.SerializerOptions{Yaml: true, Pretty: false, Strict: options.Strict},
	)
	protoSerializer := protobuf.NewSerializer(scheme, scheme)
	protoRawSerializer := protobuf.NewRawSerializer(scheme, scheme)

	serializers := []serializerType{
		jsonSerializerType,
		{
			AcceptContentTypes: []string{runtime.ContentTypeYAML},
			ContentType:        runtime.ContentTypeYAML,
			FileExtensions:     []string{"yaml"},
			EncodesAsText:      true,
			Serializer:         yamlSerializer,
		},
		{
			AcceptContentTypes: []string{runtime.ContentTypeProtobuf},
			ContentType:        runtime.ContentTypeProtobuf,
			FileExtensions:     []string{"pb"},
			Serializer:         protoSerializer,

			Framer:           protobuf.LengthDelimitedFramer,
			StreamSerializer: protoRawSerializer,
		},
	}

	for _, fn := range serializerExtensions {
		if serializer, ok := fn(scheme); ok {
			serializers = append(serializers, serializer)
		}
	}
	return serializers
}

// CodecFactory provides methods for retrieving codecs and serializers for specific
// versions and content types.
type CodecFactory struct {
	scheme      *runtime.Scheme
	serializers []serializerType
	universal   runtime.Decoder
	accepts     []runtime.SerializerInfo

	legacySerializer runtime.Serializer
}

// CodecFactoryOptions holds the options for configuring CodecFactory behavior
type CodecFactoryOptions struct {
	// Strict configures all serializers in strict mode
	Strict bool
	// Pretty includes a pretty serializer along with the non-pretty one
	Pretty bool
}

// CodecFactoryOptionsMutator takes a pointer to an options struct and then modifies it.
// Functions implementing this type can be passed to the NewCodecFactory() constructor.
type CodecFactoryOptionsMutator func(*CodecFactoryOptions)

// EnablePretty enables including a pretty serializer along with the non-pretty one
func EnablePretty(options *CodecFactoryOptions) {
	options.Pretty = true
}

// DisablePretty disables including a pretty serializer along with the non-pretty one
func DisablePretty(options *CodecFactoryOptions) {
	options.Pretty = false
}

// EnableStrict enables configuring all serializers in strict mode
func EnableStrict(options *CodecFactoryOptions) {
	options.Strict = true
}

// DisableStrict disables configuring all serializers in strict mode
func DisableStrict(options *CodecFactoryOptions) {
	options.Strict = false
}

// NewCodecFactory provides methods for retrieving serializers for the supported wire formats
// and conversion wrappers to define preferred internal and external versions. In the future,
// as the internal version is used less, callers may instead use a defaulting serializer and
// only convert objects which are shared internally (Status, common API machinery).
//
// Mutators can be passed to change the CodecFactoryOptions before construction of the factory.
// It is recommended to explicitly pass mutators instead of relying on defaults.
// By default, Pretty is enabled -- this is conformant with previously supported behavior.
//
// TODO: allow other codecs to be compiled in?
// TODO: accept a scheme interface
func NewCodecFactory(scheme *runtime.Scheme, mutators ...CodecFactoryOptionsMutator) CodecFactory {
	options := CodecFactoryOptions{Pretty: true}
	for _, fn := range mutators {
		fn(&options)
	}

	serializers := newSerializersForScheme(scheme, json.DefaultMetaFactory, options)
	return newCodecFactory(scheme, serializers)
}

// newCodecFactory is a helper for testing that allows a different metafactory to be specified.
func newCodecFactory(scheme *runtime.Scheme, serializers []serializerType) CodecFactory {
	decoders := make([]runtime.Decoder, 0, len(serializers))
	var accepts []runtime.SerializerInfo
	alreadyAccepted := make(map[string]struct{})

	var legacySerializer runtime.Serializer
	for _, d := range serializers {
		decoders = append(decoders, d.Serializer)
		for _, mediaType := range d.AcceptContentTypes {
			if _, ok := alreadyAccepted[mediaType]; ok {
				continue
			}
			alreadyAccepted[mediaType] = struct{}{}
			info := runtime.SerializerInfo{
				MediaType:        d.ContentType,
				EncodesAsText:    d.EncodesAsText,
				Serializer:       d.Serializer,
				PrettySerializer: d.PrettySerializer,
			}

			mediaType, _, err := mime.ParseMediaType(info.MediaType)
			if err != nil {
				panic(err)
			}
			parts := strings.SplitN(mediaType, "/", 2)
			info.MediaTypeType = parts[0]
			info.MediaTypeSubType = parts[1]

			if d.StreamSerializer != nil {
				info.StreamSerializer = &runtime.StreamSerializerInfo{
					Serializer:    d.StreamSerializer,
					EncodesAsText: d.EncodesAsText,
					Framer:        d.Framer,
				}
			}
			accepts = append(accepts, info)
			if mediaType == runtime.ContentTypeJSON {
				legacySerializer = d.Serializer
			}
		}
	}
	if legacySerializer == nil {
		legacySerializer = serializers[0].Serializer
	}

	return CodecFactory{
		scheme:      scheme,
		serializers: serializers,
		universal:   recognizer.NewDecoder(decoders...),

		accepts: accepts,

		legacySerializer: legacySerializer,
	}
}

// WithoutConversion returns a NegotiatedSerializer that performs no conversion, even if the
// caller requests it.
func (f CodecFactory) WithoutConversion() runtime.NegotiatedSerializer {
	return WithoutConversionCodecFactory{f}
}

// SupportedMediaTypes returns the RFC2046 media types that this factory has serializers for.
func (f CodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
	return f.accepts
}

// LegacyCodec encodes output to a given API versions, and decodes output into the internal form from
// any recognized source. The returned codec will always encode output to JSON. If a type is not
// found in the list of versions an error will be returned.
//
// This method is deprecated - clients and servers should negotiate a serializer by mime-type and
// invoke CodecForVersions. Callers that need only to read data should use UniversalDecoder().
//
// TODO: make this call exist only in pkg/api, and initialize it with the set of default versions.
//   All other callers will be forced to request a Codec directly.
func (f CodecFactory) LegacyCodec(version ...schema.GroupVersion) runtime.Codec {
	return versioning.NewDefaultingCodecForScheme(f.scheme, f.legacySerializer, f.universal, schema.GroupVersions(version), runtime.InternalGroupVersioner)
}

// UniversalDeserializer can convert any stored data recognized by this factory into a Go object that satisfies
// runtime.Object. It does not perform conversion. It does not perform defaulting.
func (f CodecFactory) UniversalDeserializer() runtime.Decoder {
	return f.universal
}

// UniversalDecoder returns a runtime.Decoder capable of decoding all known API objects in all known formats. Used
// by clients that do not need to encode objects but want to deserialize API objects stored on disk. Only decodes
// objects in groups registered with the scheme. The GroupVersions passed may be used to select alternate
// versions of objects to return - by default, runtime.APIVersionInternal is used. If any versions are specified,
// unrecognized groups will be returned in the version they are encoded as (no conversion). This decoder performs
// defaulting.
//
// TODO: the decoder will eventually be removed in favor of dealing with objects in their versioned form
// TODO: only accept a group versioner
func (f CodecFactory) UniversalDecoder(versions ...schema.GroupVersion) runtime.Decoder {
	var versioner runtime.GroupVersioner
	if len(versions) == 0 {
		versioner = runtime.InternalGroupVersioner
	} else {
		versioner = schema.GroupVersions(versions)
	}
	return f.CodecForVersions(nil, f.universal, nil, versioner)
}

// CodecForVersions creates a codec with the provided serializer. If an object is decoded and its group is not in the list,
// it will default to runtime.APIVersionInternal. If encode is not specified for an object's group, the object is not
// converted. If encode or decode are nil, no conversion is performed.
func (f CodecFactory) CodecForVersions(encoder runtime.Encoder, decoder runtime.Decoder, encode runtime.GroupVersioner, decode runtime.GroupVersioner) runtime.Codec {
	// TODO: these are for backcompat, remove them in the future
	if encode == nil {
		encode = runtime.DisabledGroupVersioner
	}
	if decode == nil {
		decode = runtime.InternalGroupVersioner
	}
	return versioning.NewDefaultingCodecForScheme(f.scheme, encoder, decoder, encode, decode)
}

// DecoderToVersion returns a decoder that targets the provided group version.
func (f CodecFactory) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
	return f.CodecForVersions(nil, decoder, nil, gv)
}

// EncoderForVersion returns an encoder that targets the provided group version.
func (f CodecFactory) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
	return f.CodecForVersions(encoder, nil, gv, nil)
}

// WithoutConversionCodecFactory is a CodecFactory that will explicitly ignore requests to perform conversion.
// This wrapper is used while code migrates away from using conversion (such as external clients) and in the future
// will be unnecessary when we change the signature of NegotiatedSerializer.
type WithoutConversionCodecFactory struct {
	CodecFactory
}

// EncoderForVersion returns an encoder that does not do conversion, but does set the group version kind of the object
// when serialized.
func (f WithoutConversionCodecFactory) EncoderForVersion(serializer runtime.Encoder, version runtime.GroupVersioner) runtime.Encoder {
	return runtime.WithVersionEncoder{
		Version:     version,
		Encoder:     serializer,
		ObjectTyper: f.CodecFactory.scheme,
	}
}

// DecoderToVersion returns an decoder that does not do conversion.
func (f WithoutConversionCodecFactory) DecoderToVersion(serializer runtime.Decoder, _ runtime.GroupVersioner) runtime.Decoder {
	return runtime.WithoutVersionDecoder{
		Decoder: serializer,
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"strings"
)

type Directive struct {
	template string
	result   string
	command  string
	tags     []string
}

func ParseDirectives(args []string) ([]Directive, error) {
	args_len := len(args)
	directives := make([]Directive, args_len)
	// for each args, parse into directives
	for i := 0; i < args_len; i = i + 1 {
		// split it into parts
		// 1st part: path to template file
		// 2nd part: path to result file
		// 3nd part: command to execute, optional
		// remaining parts: filter tags
		parts := strings.Split(args[i], ":")
		parts_len := len(parts)
		// check number
		if parts_len < 2 {
			return nil, errors.New("Syntax error")
		}
		for i := 0; i < parts_len; i = i + 1 {
			if len(parts[i]) == 0 {
				return nil, errors.New("Syntax error")
			}
		}
		// register directive
		directives[i] = Directive{
			template: parts[0],
			result:   parts[1],
		}
		if parts_len > 2 {
			directives[i].command = parts[2]
		}
		if parts_len > 3 {
			directives[i].tags = make([]string, parts_len-3)
			for j := 0; j < parts_len-3; j = j + 1 {
				directives[i].tags[j] = parts[3+j]
			}
		}
	}

	return directives, nil
}
<commit_msg>parse directive from config file<commit_after>package main

import (
	"io/ioutil"
	"encoding/json"
)

type Template struct {
	Src string
	Dest string
	Cmd string
}

type Directive struct {
	Name string
	Role string
	Status string
	Tags []string
	Rpc-addr string
	Rpc-auth string
	Templates []Template
}

func ParseDirectives(config-file string) (Directive, error) {
	config-json, err := ioutil.ReadFile(config-file)
	if err != nil {
		panic(err)
	}
	var directive Directive
	err = json.Unmarshal(config-json, &directive)
	if err != nil {
		panic(err)
	}
	return directive, nil
}
<|endoftext|>


<commit_before>// Copyright 2014 tsuru 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 testing provides fake implementations of the fs package.
//
// These implementations can be used to mock out the file system in tests.
package testing

import (
	"fmt"
	"os"
	"path"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"

	"github.com/tsuru/tsuru/fs"
	"github.com/tsuru/tsuru/safe"
)

// FakeFile representss a fake instance of the File interface.
//
// Methods from FakeFile act like methods in os.File, but instead of working in
// a real file, them work in an internal string.
//
// An instance of FakeFile is returned by RecordingFs.Open method.
type FakeFile struct {
	content string
	current int64
	r       *safe.BytesReader
	f       *os.File
}

func (f *FakeFile) reader() *safe.BytesReader {
	if f.r == nil {
		f.r = safe.NewBytesReader([]byte(f.content))
	}
	return f.r
}

func (f *FakeFile) Close() error {
	atomic.StoreInt64(&f.current, 0)
	if f.f != nil {
		f.f.Close()
		f.f = nil
	}
	return nil
}

func (f *FakeFile) Read(p []byte) (n int, err error) {
	n, err = f.reader().Read(p)
	atomic.AddInt64(&f.current, int64(n))
	return
}

func (f *FakeFile) ReadAt(p []byte, off int64) (n int, err error) {
	n, err = f.reader().ReadAt(p, off)
	atomic.AddInt64(&f.current, off+int64(n))
	return
}

func (f *FakeFile) Seek(offset int64, whence int) (int64, error) {
	ncurrent, err := f.reader().Seek(offset, whence)
	old := atomic.LoadInt64(&f.current)
	for !atomic.CompareAndSwapInt64(&f.current, old, ncurrent) {
		old = atomic.LoadInt64(&f.current)
	}
	return ncurrent, err
}

func (f *FakeFile) Fd() uintptr {
	if f.f == nil {
		var err error
		p := path.Join(os.TempDir(), "testing-fs-file.txt")
		f.f, err = os.Create(p)
		if err != nil {
			panic(err)
		}
	}
	return f.f.Fd()
}

func (f *FakeFile) Stat() (fi os.FileInfo, err error) {
	return
}

func (f *FakeFile) Write(p []byte) (n int, err error) {
	n = len(p)
	cur := atomic.LoadInt64(&f.current)
	diff := cur - int64(len(f.content))
	if diff > 0 {
		f.content += strings.Repeat("\x00", int(diff)) + string(p)
	} else {
		f.content = f.content[:cur] + string(p)
	}
	return
}

func (f *FakeFile) WriteString(s string) (ret int, err error) {
	return f.Write([]byte(s))
}

func (f *FakeFile) Truncate(size int64) error {
	f.content = f.content[:size]
	return nil
}

// RecordingFs implements the Fs interface providing a "recording" file system.
//
// A recording file system is a file system that does not execute any action,
// just record them.
//
// All methods from RecordingFs never return errors.
type RecordingFs struct {
	actions      []string
	actionsMutex sync.Mutex

	files      map[string]*FakeFile
	filesMutex sync.Mutex

	// FileContent is used to provide content for files opened using
	// RecordingFs.
	FileContent string
}

// HasAction checks if a given action was executed in the filesystem.
//
// For example, when you call the Open method with the "/tmp/file.txt"
// argument, RecordingFs will store locally the action "open /tmp/file.txt" and
// you can check it calling HasAction:
//
//     rfs.Open("/tmp/file.txt")
//     rfs.HasAction("open /tmp/file.txt") // true
func (r *RecordingFs) HasAction(action string) bool {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	for _, a := range r.actions {
		if action == a {
			return true
		}
	}
	return false
}

func (r *RecordingFs) open(name string, read bool) (fs.File, error) {
	r.filesMutex.Lock()
	defer r.filesMutex.Unlock()
	if r.files == nil {
		r.files = make(map[string]*FakeFile)
		if r.FileContent == "" && read {
			return nil, syscall.ENOENT
		}
	} else if f, ok := r.files[name]; ok {
		f.r = nil
		return f, nil
	} else if r.FileContent == "" && read {
		return nil, syscall.ENOENT
	}
	fil := &FakeFile{content: r.FileContent}
	r.files[name] = fil
	return fil, nil
}

// Create records the action "create <name>" and returns an instance of
// FakeFile and nil error.
func (r *RecordingFs) Create(name string) (fs.File, error) {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "create "+name)
	r.actionsMutex.Unlock()
	return r.open(name, false)
}

// Mkdir records the action "mkdir <name> with mode <perm>" and returns nil.
func (r *RecordingFs) Mkdir(name string, perm os.FileMode) error {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	r.actions = append(r.actions, fmt.Sprintf("mkdir %s with mode %#o", name, perm))
	return nil
}

// MkdirAll records the action "mkdirall <path> with mode <perm>" and returns
// nil.
func (r *RecordingFs) MkdirAll(path string, perm os.FileMode) error {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	r.actions = append(r.actions, fmt.Sprintf("mkdirall %s with mode %#o", path, perm))
	return nil
}

// Open records the action "open <name>" and returns an instance of FakeFile
// and nil error.
func (r *RecordingFs) Open(name string) (fs.File, error) {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "open "+name)
	r.actionsMutex.Unlock()
	return r.open(name, true)
}

// OpenFile records the action "openfile <name> with mode <perm>" and returns
// an instance of FakeFile and nil error.
func (r *RecordingFs) OpenFile(name string, flag int, perm os.FileMode) (fs.File, error) {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, fmt.Sprintf("openfile %s with mode %#o", name, perm))
	r.actionsMutex.Unlock()
	if flag&os.O_EXCL == os.O_EXCL && flag&os.O_CREATE == os.O_CREATE {
		return nil, syscall.EALREADY
	}
	read := flag&syscall.O_CREAT != syscall.O_CREAT &&
		flag&syscall.O_APPEND != syscall.O_APPEND &&
		flag&syscall.O_TRUNC != syscall.O_TRUNC &&
		flag&syscall.O_WRONLY != syscall.O_WRONLY
	f, err := r.open(name, read)
	if flag&syscall.O_TRUNC == syscall.O_TRUNC {
		f.Truncate(0)
	}
	if flag&syscall.O_APPEND == syscall.O_APPEND {
		f.Seek(0, 2)
	}
	return f, err
}

func (r *RecordingFs) deleteFile(name string) {
	r.filesMutex.Lock()
	defer r.filesMutex.Unlock()
	if r.files != nil {
		delete(r.files, name)
	}
}

// Remove records the action "remove <name>" and returns nil.
func (r *RecordingFs) Remove(name string) error {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "remove "+name)
	r.actionsMutex.Unlock()
	r.deleteFile(name)
	return nil
}

// RemoveAll records the action "removeall <path>" and returns nil.
func (r *RecordingFs) RemoveAll(path string) error {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "removeall "+path)
	r.actionsMutex.Unlock()
	r.deleteFile(path)
	return nil
}

// Rename records the action "rename <old> <new>" and returns nil.
func (r *RecordingFs) Rename(oldname, newname string) error {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "rename "+oldname+" "+newname)
	r.actionsMutex.Unlock()
	r.filesMutex.Lock()
	defer r.filesMutex.Unlock()
	if r.files == nil {
		r.files = make(map[string]*FakeFile)
	}
	r.files[newname] = r.files[oldname]
	delete(r.files, oldname)
	return nil
}

// Stat records the action "stat <name>" and returns nil, nil.
func (r *RecordingFs) Stat(name string) (os.FileInfo, error) {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	r.actions = append(r.actions, "stat "+name)
	return nil, nil
}

// FileNotFoundFs is like RecordingFs, except that it returns ENOENT on Open,
// OpenFile and Remove.
type FileNotFoundFs struct {
	RecordingFs
}

func (r *FileNotFoundFs) Open(name string) (fs.File, error) {
	r.RecordingFs.Open(name)
	err := os.PathError{Err: syscall.ENOENT, Path: name}
	return nil, &err
}

func (r *FileNotFoundFs) Remove(name string) error {
	r.RecordingFs.Remove(name)
	return &os.PathError{Err: syscall.ENOENT, Path: name}
}

func (r *FileNotFoundFs) RemoveAll(path string) error {
	r.RecordingFs.RemoveAll(path)
	return &os.PathError{Err: syscall.ENOENT, Path: path}
}

func (r *FileNotFoundFs) OpenFile(name string, flag int, perm os.FileMode) (fs.File, error) {
	r.RecordingFs.OpenFile(name, flag, perm)
	return r.Open(name)
}

// FailureFs is like RecordingFs, except the it returns an arbitrary error on
// operations.
type FailureFs struct {
	RecordingFs
	Err error
}

func (r *FailureFs) Open(name string) (fs.File, error) {
	r.RecordingFs.Open(name)
	return nil, r.Err
}
<commit_msg>fs/testing: fix typos<commit_after>// Copyright 2014 tsuru 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 testing provides fake implementations of the fs package.
//
// These implementations can be used to mock out the file system in tests.
package testing

import (
	"fmt"
	"os"
	"path"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"

	"github.com/tsuru/tsuru/fs"
	"github.com/tsuru/tsuru/safe"
)

// FakeFile represents a fake instance of the File interface.
//
// Methods from FakeFile act like methods in os.File, but instead of working in
// a real file, they work in an internal string.
//
// An instance of FakeFile is returned by RecordingFs.Open method.
type FakeFile struct {
	content string
	current int64
	r       *safe.BytesReader
	f       *os.File
}

func (f *FakeFile) reader() *safe.BytesReader {
	if f.r == nil {
		f.r = safe.NewBytesReader([]byte(f.content))
	}
	return f.r
}

func (f *FakeFile) Close() error {
	atomic.StoreInt64(&f.current, 0)
	if f.f != nil {
		f.f.Close()
		f.f = nil
	}
	return nil
}

func (f *FakeFile) Read(p []byte) (n int, err error) {
	n, err = f.reader().Read(p)
	atomic.AddInt64(&f.current, int64(n))
	return
}

func (f *FakeFile) ReadAt(p []byte, off int64) (n int, err error) {
	n, err = f.reader().ReadAt(p, off)
	atomic.AddInt64(&f.current, off+int64(n))
	return
}

func (f *FakeFile) Seek(offset int64, whence int) (int64, error) {
	ncurrent, err := f.reader().Seek(offset, whence)
	old := atomic.LoadInt64(&f.current)
	for !atomic.CompareAndSwapInt64(&f.current, old, ncurrent) {
		old = atomic.LoadInt64(&f.current)
	}
	return ncurrent, err
}

func (f *FakeFile) Fd() uintptr {
	if f.f == nil {
		var err error
		p := path.Join(os.TempDir(), "testing-fs-file.txt")
		f.f, err = os.Create(p)
		if err != nil {
			panic(err)
		}
	}
	return f.f.Fd()
}

func (f *FakeFile) Stat() (fi os.FileInfo, err error) {
	return
}

func (f *FakeFile) Write(p []byte) (n int, err error) {
	n = len(p)
	cur := atomic.LoadInt64(&f.current)
	diff := cur - int64(len(f.content))
	if diff > 0 {
		f.content += strings.Repeat("\x00", int(diff)) + string(p)
	} else {
		f.content = f.content[:cur] + string(p)
	}
	return
}

func (f *FakeFile) WriteString(s string) (ret int, err error) {
	return f.Write([]byte(s))
}

func (f *FakeFile) Truncate(size int64) error {
	f.content = f.content[:size]
	return nil
}

// RecordingFs implements the Fs interface providing a "recording" file system.
//
// A recording file system is a file system that does not execute any action,
// just record them.
//
// All methods from RecordingFs never return errors.
type RecordingFs struct {
	actions      []string
	actionsMutex sync.Mutex

	files      map[string]*FakeFile
	filesMutex sync.Mutex

	// FileContent is used to provide content for files opened using
	// RecordingFs.
	FileContent string
}

// HasAction checks if a given action was executed in the filesystem.
//
// For example, when you call the Open method with the "/tmp/file.txt"
// argument, RecordingFs will store locally the action "open /tmp/file.txt" and
// you can check it calling HasAction:
//
//     rfs.Open("/tmp/file.txt")
//     rfs.HasAction("open /tmp/file.txt") // true
func (r *RecordingFs) HasAction(action string) bool {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	for _, a := range r.actions {
		if action == a {
			return true
		}
	}
	return false
}

func (r *RecordingFs) open(name string, read bool) (fs.File, error) {
	r.filesMutex.Lock()
	defer r.filesMutex.Unlock()
	if r.files == nil {
		r.files = make(map[string]*FakeFile)
		if r.FileContent == "" && read {
			return nil, syscall.ENOENT
		}
	} else if f, ok := r.files[name]; ok {
		f.r = nil
		return f, nil
	} else if r.FileContent == "" && read {
		return nil, syscall.ENOENT
	}
	fil := &FakeFile{content: r.FileContent}
	r.files[name] = fil
	return fil, nil
}

// Create records the action "create <name>" and returns an instance of
// FakeFile and nil error.
func (r *RecordingFs) Create(name string) (fs.File, error) {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "create "+name)
	r.actionsMutex.Unlock()
	return r.open(name, false)
}

// Mkdir records the action "mkdir <name> with mode <perm>" and returns nil.
func (r *RecordingFs) Mkdir(name string, perm os.FileMode) error {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	r.actions = append(r.actions, fmt.Sprintf("mkdir %s with mode %#o", name, perm))
	return nil
}

// MkdirAll records the action "mkdirall <path> with mode <perm>" and returns
// nil.
func (r *RecordingFs) MkdirAll(path string, perm os.FileMode) error {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	r.actions = append(r.actions, fmt.Sprintf("mkdirall %s with mode %#o", path, perm))
	return nil
}

// Open records the action "open <name>" and returns an instance of FakeFile
// and nil error.
func (r *RecordingFs) Open(name string) (fs.File, error) {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "open "+name)
	r.actionsMutex.Unlock()
	return r.open(name, true)
}

// OpenFile records the action "openfile <name> with mode <perm>" and returns
// an instance of FakeFile and nil error.
func (r *RecordingFs) OpenFile(name string, flag int, perm os.FileMode) (fs.File, error) {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, fmt.Sprintf("openfile %s with mode %#o", name, perm))
	r.actionsMutex.Unlock()
	if flag&os.O_EXCL == os.O_EXCL && flag&os.O_CREATE == os.O_CREATE {
		return nil, syscall.EALREADY
	}
	read := flag&syscall.O_CREAT != syscall.O_CREAT &&
		flag&syscall.O_APPEND != syscall.O_APPEND &&
		flag&syscall.O_TRUNC != syscall.O_TRUNC &&
		flag&syscall.O_WRONLY != syscall.O_WRONLY
	f, err := r.open(name, read)
	if flag&syscall.O_TRUNC == syscall.O_TRUNC {
		f.Truncate(0)
	}
	if flag&syscall.O_APPEND == syscall.O_APPEND {
		f.Seek(0, 2)
	}
	return f, err
}

func (r *RecordingFs) deleteFile(name string) {
	r.filesMutex.Lock()
	defer r.filesMutex.Unlock()
	if r.files != nil {
		delete(r.files, name)
	}
}

// Remove records the action "remove <name>" and returns nil.
func (r *RecordingFs) Remove(name string) error {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "remove "+name)
	r.actionsMutex.Unlock()
	r.deleteFile(name)
	return nil
}

// RemoveAll records the action "removeall <path>" and returns nil.
func (r *RecordingFs) RemoveAll(path string) error {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "removeall "+path)
	r.actionsMutex.Unlock()
	r.deleteFile(path)
	return nil
}

// Rename records the action "rename <old> <new>" and returns nil.
func (r *RecordingFs) Rename(oldname, newname string) error {
	r.actionsMutex.Lock()
	r.actions = append(r.actions, "rename "+oldname+" "+newname)
	r.actionsMutex.Unlock()
	r.filesMutex.Lock()
	defer r.filesMutex.Unlock()
	if r.files == nil {
		r.files = make(map[string]*FakeFile)
	}
	r.files[newname] = r.files[oldname]
	delete(r.files, oldname)
	return nil
}

// Stat records the action "stat <name>" and returns nil, nil.
func (r *RecordingFs) Stat(name string) (os.FileInfo, error) {
	r.actionsMutex.Lock()
	defer r.actionsMutex.Unlock()
	r.actions = append(r.actions, "stat "+name)
	return nil, nil
}

// FileNotFoundFs is like RecordingFs, except that it returns ENOENT on Open,
// OpenFile and Remove.
type FileNotFoundFs struct {
	RecordingFs
}

func (r *FileNotFoundFs) Open(name string) (fs.File, error) {
	r.RecordingFs.Open(name)
	err := os.PathError{Err: syscall.ENOENT, Path: name}
	return nil, &err
}

func (r *FileNotFoundFs) Remove(name string) error {
	r.RecordingFs.Remove(name)
	return &os.PathError{Err: syscall.ENOENT, Path: name}
}

func (r *FileNotFoundFs) RemoveAll(path string) error {
	r.RecordingFs.RemoveAll(path)
	return &os.PathError{Err: syscall.ENOENT, Path: path}
}

func (r *FileNotFoundFs) OpenFile(name string, flag int, perm os.FileMode) (fs.File, error) {
	r.RecordingFs.OpenFile(name, flag, perm)
	return r.Open(name)
}

// FailureFs is like RecordingFs, except the it returns an arbitrary error on
// operations.
type FailureFs struct {
	RecordingFs
	Err error
}

func (r *FailureFs) Open(name string) (fs.File, error) {
	r.RecordingFs.Open(name)
	return nil, r.Err
}
<|endoftext|>


<commit_before>package cbuildd

import (
	"bytes"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// Helper functions
func StrsEquals(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}

type ParseTestCase struct {
	inputArgs []string
	b         Build // Resulting build object
}

func TestParseArgs(t *testing.T) {
	// Note args is left out of the Build struct because it supplied separately
	testData := []ParseTestCase{
		ParseTestCase{
			inputArgs: []string{"-c", "data/main.c", "-o", "main.o"},
			b: Build{
				Oindex:      3,
				Iindex:      1,
				Cindex:      0,
				LinkCommand: false,
			},
		},
	}

	// Check each test case
	for _, tc := range testData {
		// Make sure to set the args for the test case
		args := tc.inputArgs
		eb := tc.b
		eb.Args = args

		b := ParseArgs(args)

		// Make sure the args match
		if !StrsEquals(args, b.Args) {
			t.Errorf("Args are wrong")
		}

		// Make sure we parsed the output properly
		if eb.Output() != b.Output() {
			t.Errorf("Output path wrong")
		}

		if eb.Oindex != b.Oindex {
			t.Errorf("Output index wrong")
		}

		// Now lets do the input
		if eb.Iindex != b.Iindex {
			t.Errorf("Input index wrong")
		}

		if "data/main.c" != b.Args[b.Iindex] {
			t.Errorf("Input path wrong")
		}

		// Now lets test the link command is properly recognized
		if eb.LinkCommand != b.LinkCommand {
			t.Errorf("Should not be b a link command")
		}
	}
}

func TestTempFile(t *testing.T) {
	f, err := TempFile("", "cbd-test-", ".test")

	if err != nil {
		t.Errorf("Error:", err)
	}

	name := f.Name()

	defer os.Remove(name)

	// Now lets check the file
	prefix := filepath.Join(os.TempDir(), "cbd-test-")
	suffix := ".test"

	if !strings.HasPrefix(name, prefix) {
		t.Errorf("Error '%s' does not have prefix: '%s'", name, prefix)
	}

	if !strings.HasSuffix(name, suffix) {
		t.Errorf("Error '%s' does not have suffix: '%s'", name, suffix)
	}
}

// Put in a test for RunCmd here, make sure we are getting back stderr and stdout
func TestRunCmd(t *testing.T) {
	tests := map[string]ExecResult{
		"go version": ExecResult{
			Output: bytes.NewBufferString("go version go1.2 linux/amd64\n"),
			Return: 0,
		},
		"go bob": ExecResult{
			Output: bytes.NewBufferString("go: unknown subcommand \"bob\"\nRun 'go help' for usage.\n"),
			Return: 2,
		},
	}

	for cmd, eres := range tests {
		// Split up string to get the command and it's args
		args := strings.Split(cmd, " ")

		res, err := RunCmd(args[0], args[1:])

		// Ignore the errors that occur with non-zero return codes
		if eres.Return == 0 {
			if err != nil {
				t.Errorf("Run command failed with: %s", err)
			}
		}

		// Now check our results
		if res.Return != eres.Return {
			t.Errorf("Got return: %d instead of: %d", eres.Return, res.Return)
		}

		if res.Output.String() != eres.Output.String() {
			t.Errorf("Got output: %s instead of: %s", res.Output.String(),
				eres.Output.String())
		}
	}
}
<commit_msg>Added tests for the Compile and Preprocess functions<commit_after>package cbuildd

import (
	"bytes"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

// Helper functions
func StrsEquals(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i, v := range a {
		if v != b[i] {
			return false
		}
	}
	return true
}

type ParseTestCase struct {
	inputArgs []string
	b         Build // Resulting build object
}

func TestParseArgs(t *testing.T) {
	// Note args is left out of the Build struct because it supplied separately
	testData := []ParseTestCase{
		ParseTestCase{
			inputArgs: []string{"-c", "data/main.c", "-o", "main.o"},
			b: Build{
				Oindex:      3,
				Iindex:      1,
				Cindex:      0,
				LinkCommand: false,
			},
		},
	}

	// Check each test case
	for _, tc := range testData {
		// Make sure to set the args for the test case
		args := tc.inputArgs
		eb := tc.b
		eb.Args = args

		b := ParseArgs(args)

		// Make sure the args match
		if !StrsEquals(args, b.Args) {
			t.Errorf("Args are wrong")
		}

		// Make sure we parsed the output properly
		if eb.Output() != b.Output() {
			t.Errorf("Output path wrong")
		}

		if eb.Oindex != b.Oindex {
			t.Errorf("Output index wrong")
		}

		// Now lets do the input
		if eb.Iindex != b.Iindex {
			t.Errorf("Input index wrong")
		}

		if "data/main.c" != b.Args[b.Iindex] {
			t.Errorf("Input path wrong")
		}

		// Now lets test the link command is properly recognized
		if eb.LinkCommand != b.LinkCommand {
			t.Errorf("Should not be b a link command")
		}
	}
}

func TestTempFile(t *testing.T) {
	f, err := TempFile("", "cbd-test-", ".test")

	if err != nil {
		t.Errorf("Error:", err)
	}

	name := f.Name()

	defer os.Remove(name)

	// Now lets check the file
	prefix := filepath.Join(os.TempDir(), "cbd-test-")
	suffix := ".test"

	if !strings.HasPrefix(name, prefix) {
		t.Errorf("Error '%s' does not have prefix: '%s'", name, prefix)
	}

	if !strings.HasSuffix(name, suffix) {
		t.Errorf("Error '%s' does not have suffix: '%s'", name, suffix)
	}
}

// Put in a test for RunCmd here, make sure we are getting back stderr and stdout
func TestRunCmd(t *testing.T) {
	tests := map[string]ExecResult{
		"go version": ExecResult{
			Output: bytes.NewBufferString("go version go1.2 linux/amd64\n"),
			Return: 0,
		},
		"go bob": ExecResult{
			Output: bytes.NewBufferString("go: unknown subcommand \"bob\"\nRun 'go help' for usage.\n"),
			Return: 2,
		},
	}

	for cmd, eres := range tests {
		// Split up string to get the command and it's args
		args := strings.Split(cmd, " ")

		res, err := RunCmd(args[0], args[1:])

		// Ignore the errors that occur with non-zero return codes
		if eres.Return == 0 {
			if err != nil {
				t.Errorf("Run command failed with: %s", err)
			}
		}

		// Now check our results
		if res.Return != eres.Return {
			t.Errorf("Got return: %d instead of: %d", eres.Return, res.Return)
		}

		if res.Output.String() != eres.Output.String() {
			t.Errorf("Got output: %s instead of: %s", res.Output.String(),
				eres.Output.String())
		}
	}
}

// This test requires gcc to be installed
func TestPreprocess(t *testing.T) {
	b := ParseArgs(strings.Split("-c data/main.c -o main.o", " "))
	filePath, result, err := Preprocess("gcc", b)

	if err != nil {
		t.Errorf("Preprocess returned error: %s (Output: %s)", err,
			result.Output.String())
	}

	if result.Return != 0 {
		t.Errorf("Preprocess returned: %d", result.Return)
	}

	// Make sure we have the right extension
	ext := filepath.Ext(filePath)
	if ext != ".c" {
		t.Error("File does not have required .c extension has:", ext)
	}

	// Make sure the file exists
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		t.Error("Output file does not exist:", filePath)
		return
	} else {
		//defer os.Remove(filePath)
	}

	// Makes sure the file contains C source code
	contents, err := ioutil.ReadFile(filePath)

	if err != nil {
		t.Error("Could not read file:", err)
	}

	if !bytes.Contains(contents, []byte("printf(\"Hello, world!\\n\");")) {
		t.Error("Output didn't contain C code:",string(contents))
	}
}

// This test requires gcc to be installed
func TestCompile(t *testing.T) {
	// Create a temporary file and copy the C source code into that location
	f, err := TempFile("", "cbd-test-", ".c")
	tempFile := f.Name()

	defer os.Remove(tempFile)

	Copyfile(tempFile, "data/main.c")

	// Now lets build that temp code
	b := ParseArgs(strings.Split("-c data/nothere.c -o main.o", " "))
	filePath, result, err := Compile("gcc", b, tempFile)

	if err != nil {
		t.Errorf("Compile returned error: %s (Output: %s)", err,
			result.Output.String())
	}

	if result.Return != 0 {
		t.Errorf("Compile returned: %d", result.Return)
	}

	// Make sure we have the right extension
	ext := filepath.Ext(filePath)
	if ext != ".o" {
		t.Error("File does not have required .o extension has:", ext)
	}

	// Make sure the file exists
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		t.Error("Output file does not exist:", filePath)
		return
	}

	// TODO: Make sure the file contains object code
}
<|endoftext|>