<commit_before>package ibclient

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"errors"
	"fmt"
	"golang.org/x/net/publicsuffix"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
	"time"
)

type HostConfig struct {
	Host     string
	Version  string
	Port     string
	Username string
	Password string
}

type TransportConfig struct {
	SslVerify           bool
	certPool            *x509.CertPool
	HttpRequestTimeout  time.Duration // in seconds
	HttpPoolConnections int
}

func NewTransportConfig(sslVerify string, httpRequestTimeout int, httpPoolConnections int) (cfg TransportConfig) {
	switch {
	case "false" == strings.ToLower(sslVerify):
		cfg.SslVerify = false
	case "true" == strings.ToLower(sslVerify):
		cfg.SslVerify = true
	default:
		caPool := x509.NewCertPool()
		cert, err := ioutil.ReadFile(sslVerify)
		if err != nil {
			log.Printf("Cannot load certificate file '%s'", sslVerify)
			return
		}
		if !caPool.AppendCertsFromPEM(cert) {
			err = errors.New(fmt.Sprintf("Cannot append certificate from file '%s'", sslVerify))
			return
		}
		cfg.certPool = caPool
		cfg.SslVerify = true
	}

	cfg.HttpPoolConnections = httpPoolConnections
	cfg.HttpRequestTimeout = time.Duration(httpRequestTimeout)
	return
}

type HttpRequestBuilder interface {
	Init(HostConfig)
	BuildUrl(r RequestType, objType string, ref string, returnFields []string) (urlStr string)
	BuildBody(r RequestType, obj IBObject) (jsonStr []byte)
	BuildRequest(r RequestType, obj IBObject, ref string) (req *http.Request, err error)
}

type HttpRequestor interface {
	Init(TransportConfig)
	SendRequest(*http.Request) ([]byte, error)
}

type WapiRequestBuilder struct {
	HostConfig HostConfig
}

type WapiHttpRequestor struct {
	client http.Client
}

type IBConnector interface {
	CreateObject(obj IBObject) (ref string, err error)
	GetObject(obj IBObject, ref string, res interface{}) error
	DeleteObject(ref string) (refRes string, err error)
	UpdateObject(obj IBObject, ref string) (refRes string, err error)
}

type Connector struct {
	HostConfig      HostConfig
	TransportConfig TransportConfig
	RequestBuilder  HttpRequestBuilder
	Requestor       HttpRequestor
}

type RequestType int

const (
	CREATE RequestType = iota
	GET
	DELETE
	UPDATE
)

func (r RequestType) toMethod() string {
	switch r {
	case CREATE:
		return "POST"
	case GET:
		return "GET"
	case DELETE:
		return "DELETE"
	case UPDATE:
		return "PUT"
	}

	return ""
}

func getHttpResponseError(resp *http.Response) error {
	defer resp.Body.Close()
	content, _ := ioutil.ReadAll(resp.Body)
	msg := fmt.Sprintf("WAPI request error: %d('%s')\nContents:\n%s\n", resp.StatusCode, resp.Status, content)
	log.Printf(msg)
	return errors.New(msg)
}

func (whr *WapiHttpRequestor) Init(cfg TransportConfig) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: !cfg.SslVerify,
			RootCAs: cfg.certPool},
		MaxIdleConnsPerHost:   cfg.HttpPoolConnections,
		ResponseHeaderTimeout: cfg.HttpRequestTimeout * time.Second,
	}

	// All users of cookiejar should import "golang.org/x/net/publicsuffix"
	jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
	if err != nil {
		log.Fatal(err)
	}

	whr.client = http.Client{Jar: jar, Transport: tr}
}

func (whr *WapiHttpRequestor) SendRequest(req *http.Request) (res []byte, err error) {
	var resp *http.Response
	resp, err = whr.client.Do(req)
	if err != nil {
		return
	} else if !(resp.StatusCode == http.StatusOK ||
		(resp.StatusCode == http.StatusCreated &&
			req.Method == RequestType(CREATE).toMethod())) {
		err := getHttpResponseError(resp)
		return nil, err
	}
	defer resp.Body.Close()
	res, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Http Reponse ioutil.ReadAll() Error: '%s'", err)
		return
	}

	return
}

func (wrb *WapiRequestBuilder) Init(cfg HostConfig) {
	wrb.HostConfig = cfg
}

func (wrb *WapiRequestBuilder) BuildUrl(t RequestType, objType string, ref string, returnFields []string) (urlStr string) {
	path := []string{"wapi", "v" + wrb.HostConfig.Version}
	if len(ref) > 0 {
		path = append(path, ref)
	} else {
		path = append(path, objType)
	}

	qry := ""
	vals := url.Values{}
	if t == GET {
		if len(returnFields) > 0 {
			vals.Set("_return_fields", strings.Join(returnFields, ","))
		}
		qry = vals.Encode()
	}

	u := url.URL{
		Scheme:   "https",
		Host:     wrb.HostConfig.Host + ":" + wrb.HostConfig.Port,
		Path:     strings.Join(path, "/"),
		RawQuery: qry,
	}

	return u.String()
}

func (wrb *WapiRequestBuilder) BuildBody(t RequestType, obj IBObject) []byte {
	var objJson []byte
	var err error

	objJson, err = json.Marshal(obj)
	if err != nil {
		log.Printf("Cannot marshal object '%s': %s", obj, err)
		return nil
	}

	eaSearch := obj.EaSearch()
	if t == GET && len(eaSearch) > 0 {
		eaSearchJson, err := json.Marshal(eaSearch)
		if err != nil {
			log.Printf("Cannot marshal EA Search attributes. '%s'\n", err)
			return nil
		}
		objJson = append(append(objJson[:len(objJson)-1], byte(',')), eaSearchJson[1:]...)
	}

	return objJson
}

func (wrb *WapiRequestBuilder) BuildRequest(t RequestType, obj IBObject, ref string) (req *http.Request, err error) {
	var (
		objType      string
		returnFields []string
	)
	if obj != nil {
		objType = obj.ObjectType()
		returnFields = obj.ReturnFields()
	}
	urlStr := wrb.BuildUrl(t, objType, ref, returnFields)

	var bodyStr []byte
	if obj != nil {
		bodyStr = wrb.BuildBody(t, obj)
	}

	req, err = http.NewRequest(t.toMethod(), urlStr, bytes.NewBuffer(bodyStr))
	if err != nil {
		log.Printf("err1: '%s'", err)
		return
	}
	req.Header.Set("Content-Type", "application/json")
	req.SetBasicAuth(wrb.HostConfig.Username, wrb.HostConfig.Password)

	return
}

func (c *Connector) makeRequest(t RequestType, obj IBObject, ref string) (res []byte, err error) {
	var req *http.Request
	req, err = c.RequestBuilder.BuildRequest(t, obj, ref)
	res, err = c.Requestor.SendRequest(req)

	return
}

func (c *Connector) CreateObject(obj IBObject) (ref string, err error) {
	ref = ""

	resp, err := c.makeRequest(CREATE, obj, "")
	if err != nil || len(resp) == 0 {
		log.Printf("CreateObject request error: '%s'\n", err)
		return
	}

	err = json.Unmarshal(resp, &ref)
	if err != nil {
		log.Printf("Cannot unmarshall '%s', err: '%s'\n", string(resp), err)
		return
	}

	return
}

func (c *Connector) GetObject(obj IBObject, ref string, res interface{}) (err error) {
	resp, err := c.makeRequest(GET, obj, ref)
	if err != nil {
		log.Printf("GetObject request error: '%s'\n", err)
	}

	if len(resp) == 0 {
		return
	}

	err = json.Unmarshal(resp, res)

	if err != nil {
		log.Printf("Cannot unmarshall '%s', err: '%s'\n", string(resp), err)
		return
	}

	return
}

func (c *Connector) DeleteObject(ref string) (refRes string, err error) {
	refRes = ""

	resp, err := c.makeRequest(DELETE, nil, ref)
	if err != nil {
		log.Printf("DeleteObject request error: '%s'\n", err)
		return
	}

	err = json.Unmarshal(resp, &refRes)
	if err != nil {
		log.Printf("Cannot unmarshall '%s', err: '%s'\n", string(resp), err)
		return
	}

	return
}

func (c *Connector) UpdateObject(obj IBObject, ref string) (refRes string, err error) {

	refRes = ""
	resp, err := c.makeRequest(UPDATE, obj, ref)
	if err != nil {
		log.Printf("Failed to update object %s: %s", obj.ObjectType(), err)
		return
	}

	err = json.Unmarshal(resp, &refRes)
	if err != nil {
		log.Printf("Cannot unmarshall update object response'%s', err: '%s'\n", string(resp), err)
		return
	}
	return
}

// Logout sends a request to invalidate the ibapauth cookie and should
// be used in a defer statement after the Connector has been successfully
// initialized.
func (c *Connector) Logout() (err error) {
	_, err = c.makeRequest(CREATE, nil, "logout")
	if err != nil {
		log.Printf("Logout request error: '%s'\n", err)
	}

	return
}

var ValidateConnector = validateConnector

func validateConnector(c *Connector) (err error) {
	// GET UserProfile request is used here to validate connector's basic auth and reachability.
	var response []UserProfile
	userprofile := NewUserProfile(UserProfile{})
	err = c.GetObject(userprofile, "", &response)
	if err != nil {
		log.Printf("Failed to connect to the Grid, err: %s \n", err)
	}
	return
}

func NewConnector(hostConfig HostConfig, transportConfig TransportConfig,
	requestBuilder HttpRequestBuilder, requestor HttpRequestor) (res *Connector, err error) {
	res = nil

	connector := &Connector{
		HostConfig:      hostConfig,
		TransportConfig: transportConfig,
	}

	//connector.RequestBuilder = WapiRequestBuilder{WaipHostConfig: connector.HostConfig}
	connector.RequestBuilder = requestBuilder
	connector.RequestBuilder.Init(connector.HostConfig)

	connector.Requestor = requestor
	connector.Requestor.Init(connector.TransportConfig)

	res = connector
	err = ValidateConnector(connector)
	return
}
<commit_msg>connector.go: Fix internal golint suggestions. (#42)<commit_after>package ibclient

import (
	"bytes"
	"crypto/tls"
	"crypto/x509"
	"encoding/json"
	"errors"
	"fmt"
	"golang.org/x/net/publicsuffix"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
	"time"
)

type HostConfig struct {
	Host     string
	Version  string
	Port     string
	Username string
	Password string
}

type TransportConfig struct {
	SslVerify           bool
	certPool            *x509.CertPool
	HttpRequestTimeout  time.Duration // in seconds
	HttpPoolConnections int
}

func NewTransportConfig(sslVerify string, httpRequestTimeout int, httpPoolConnections int) (cfg TransportConfig) {
	switch {
	case "false" == strings.ToLower(sslVerify):
		cfg.SslVerify = false
	case "true" == strings.ToLower(sslVerify):
		cfg.SslVerify = true
	default:
		caPool := x509.NewCertPool()
		cert, err := ioutil.ReadFile(sslVerify)
		if err != nil {
			log.Printf("Cannot load certificate file '%s'", sslVerify)
			return
		}
		if !caPool.AppendCertsFromPEM(cert) {
			err = fmt.Errorf("Cannot append certificate from file '%s'", sslVerify)
			return
		}
		cfg.certPool = caPool
		cfg.SslVerify = true
	}

	cfg.HttpPoolConnections = httpPoolConnections
	cfg.HttpRequestTimeout = time.Duration(httpRequestTimeout)
	return
}

type HttpRequestBuilder interface {
	Init(HostConfig)
	BuildUrl(r RequestType, objType string, ref string, returnFields []string) (urlStr string)
	BuildBody(r RequestType, obj IBObject) (jsonStr []byte)
	BuildRequest(r RequestType, obj IBObject, ref string) (req *http.Request, err error)
}

type HttpRequestor interface {
	Init(TransportConfig)
	SendRequest(*http.Request) ([]byte, error)
}

type WapiRequestBuilder struct {
	HostConfig HostConfig
}

type WapiHttpRequestor struct {
	client http.Client
}

type IBConnector interface {
	CreateObject(obj IBObject) (ref string, err error)
	GetObject(obj IBObject, ref string, res interface{}) error
	DeleteObject(ref string) (refRes string, err error)
	UpdateObject(obj IBObject, ref string) (refRes string, err error)
}

type Connector struct {
	HostConfig      HostConfig
	TransportConfig TransportConfig
	RequestBuilder  HttpRequestBuilder
	Requestor       HttpRequestor
}

type RequestType int

const (
	CREATE RequestType = iota
	GET
	DELETE
	UPDATE
)

func (r RequestType) toMethod() string {
	switch r {
	case CREATE:
		return "POST"
	case GET:
		return "GET"
	case DELETE:
		return "DELETE"
	case UPDATE:
		return "PUT"
	}

	return ""
}

func getHTTPResponseError(resp *http.Response) error {
	defer resp.Body.Close()
	content, _ := ioutil.ReadAll(resp.Body)
	msg := fmt.Sprintf("WAPI request error: %d('%s')\nContents:\n%s\n", resp.StatusCode, resp.Status, content)
	log.Printf(msg)
	return errors.New(msg)
}

func (whr *WapiHttpRequestor) Init(cfg TransportConfig) {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: !cfg.SslVerify,
			RootCAs: cfg.certPool},
		MaxIdleConnsPerHost:   cfg.HttpPoolConnections,
		ResponseHeaderTimeout: cfg.HttpRequestTimeout * time.Second,
	}

	// All users of cookiejar should import "golang.org/x/net/publicsuffix"
	jar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})
	if err != nil {
		log.Fatal(err)
	}

	whr.client = http.Client{Jar: jar, Transport: tr}
}

func (whr *WapiHttpRequestor) SendRequest(req *http.Request) (res []byte, err error) {
	var resp *http.Response
	resp, err = whr.client.Do(req)
	if err != nil {
		return
	} else if !(resp.StatusCode == http.StatusOK ||
		(resp.StatusCode == http.StatusCreated &&
			req.Method == RequestType(CREATE).toMethod())) {
		err := getHTTPResponseError(resp)
		return nil, err
	}
	defer resp.Body.Close()
	res, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Http Reponse ioutil.ReadAll() Error: '%s'", err)
		return
	}

	return
}

func (wrb *WapiRequestBuilder) Init(cfg HostConfig) {
	wrb.HostConfig = cfg
}

func (wrb *WapiRequestBuilder) BuildUrl(t RequestType, objType string, ref string, returnFields []string) (urlStr string) {
	path := []string{"wapi", "v" + wrb.HostConfig.Version}
	if len(ref) > 0 {
		path = append(path, ref)
	} else {
		path = append(path, objType)
	}

	qry := ""
	vals := url.Values{}
	if t == GET {
		if len(returnFields) > 0 {
			vals.Set("_return_fields", strings.Join(returnFields, ","))
		}
		qry = vals.Encode()
	}

	u := url.URL{
		Scheme:   "https",
		Host:     wrb.HostConfig.Host + ":" + wrb.HostConfig.Port,
		Path:     strings.Join(path, "/"),
		RawQuery: qry,
	}

	return u.String()
}

func (wrb *WapiRequestBuilder) BuildBody(t RequestType, obj IBObject) []byte {
	var objJSON []byte
	var err error

	objJSON, err = json.Marshal(obj)
	if err != nil {
		log.Printf("Cannot marshal object '%s': %s", obj, err)
		return nil
	}

	eaSearch := obj.EaSearch()
	if t == GET && len(eaSearch) > 0 {
		eaSearchJSON, err := json.Marshal(eaSearch)
		if err != nil {
			log.Printf("Cannot marshal EA Search attributes. '%s'\n", err)
			return nil
		}
		objJSON = append(append(objJSON[:len(objJSON)-1], byte(',')), eaSearchJSON[1:]...)
	}

	return objJSON
}

func (wrb *WapiRequestBuilder) BuildRequest(t RequestType, obj IBObject, ref string) (req *http.Request, err error) {
	var (
		objType      string
		returnFields []string
	)
	if obj != nil {
		objType = obj.ObjectType()
		returnFields = obj.ReturnFields()
	}
	urlStr := wrb.BuildUrl(t, objType, ref, returnFields)

	var bodyStr []byte
	if obj != nil {
		bodyStr = wrb.BuildBody(t, obj)
	}

	req, err = http.NewRequest(t.toMethod(), urlStr, bytes.NewBuffer(bodyStr))
	if err != nil {
		log.Printf("err1: '%s'", err)
		return
	}
	req.Header.Set("Content-Type", "application/json")
	req.SetBasicAuth(wrb.HostConfig.Username, wrb.HostConfig.Password)

	return
}

func (c *Connector) makeRequest(t RequestType, obj IBObject, ref string) (res []byte, err error) {
	var req *http.Request
	req, err = c.RequestBuilder.BuildRequest(t, obj, ref)
	res, err = c.Requestor.SendRequest(req)

	return
}

func (c *Connector) CreateObject(obj IBObject) (ref string, err error) {
	ref = ""

	resp, err := c.makeRequest(CREATE, obj, "")
	if err != nil || len(resp) == 0 {
		log.Printf("CreateObject request error: '%s'\n", err)
		return
	}

	err = json.Unmarshal(resp, &ref)
	if err != nil {
		log.Printf("Cannot unmarshall '%s', err: '%s'\n", string(resp), err)
		return
	}

	return
}

func (c *Connector) GetObject(obj IBObject, ref string, res interface{}) (err error) {
	resp, err := c.makeRequest(GET, obj, ref)
	if err != nil {
		log.Printf("GetObject request error: '%s'\n", err)
	}

	if len(resp) == 0 {
		return
	}

	err = json.Unmarshal(resp, res)

	if err != nil {
		log.Printf("Cannot unmarshall '%s', err: '%s'\n", string(resp), err)
		return
	}

	return
}

func (c *Connector) DeleteObject(ref string) (refRes string, err error) {
	refRes = ""

	resp, err := c.makeRequest(DELETE, nil, ref)
	if err != nil {
		log.Printf("DeleteObject request error: '%s'\n", err)
		return
	}

	err = json.Unmarshal(resp, &refRes)
	if err != nil {
		log.Printf("Cannot unmarshall '%s', err: '%s'\n", string(resp), err)
		return
	}

	return
}

func (c *Connector) UpdateObject(obj IBObject, ref string) (refRes string, err error) {

	refRes = ""
	resp, err := c.makeRequest(UPDATE, obj, ref)
	if err != nil {
		log.Printf("Failed to update object %s: %s", obj.ObjectType(), err)
		return
	}

	err = json.Unmarshal(resp, &refRes)
	if err != nil {
		log.Printf("Cannot unmarshall update object response'%s', err: '%s'\n", string(resp), err)
		return
	}
	return
}

// Logout sends a request to invalidate the ibapauth cookie and should
// be used in a defer statement after the Connector has been successfully
// initialized.
func (c *Connector) Logout() (err error) {
	_, err = c.makeRequest(CREATE, nil, "logout")
	if err != nil {
		log.Printf("Logout request error: '%s'\n", err)
	}

	return
}

var ValidateConnector = validateConnector

func validateConnector(c *Connector) (err error) {
	// GET UserProfile request is used here to validate connector's basic auth and reachability.
	var response []UserProfile
	userprofile := NewUserProfile(UserProfile{})
	err = c.GetObject(userprofile, "", &response)
	if err != nil {
		log.Printf("Failed to connect to the Grid, err: %s \n", err)
	}
	return
}

func NewConnector(hostConfig HostConfig, transportConfig TransportConfig,
	requestBuilder HttpRequestBuilder, requestor HttpRequestor) (res *Connector, err error) {
	res = nil

	connector := &Connector{
		HostConfig:      hostConfig,
		TransportConfig: transportConfig,
	}

	//connector.RequestBuilder = WapiRequestBuilder{WaipHostConfig: connector.HostConfig}
	connector.RequestBuilder = requestBuilder
	connector.RequestBuilder.Init(connector.HostConfig)

	connector.Requestor = requestor
	connector.Requestor.Init(connector.TransportConfig)

	res = connector
	err = ValidateConnector(connector)
	return
}
<|endoftext|>


<commit_before>package task

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"strconv"
	"sync"
	"sync/atomic"

	"github.com/go-task/task/v2/internal/compiler"
	compilerv2 "github.com/go-task/task/v2/internal/compiler/v2"
	"github.com/go-task/task/v2/internal/execext"
	"github.com/go-task/task/v2/internal/logger"
	"github.com/go-task/task/v2/internal/output"
	"github.com/go-task/task/v2/internal/summary"
	"github.com/go-task/task/v2/internal/taskfile"
	"github.com/go-task/task/v2/internal/taskfile/read"

	"golang.org/x/sync/errgroup"
)

const (
	// MaximumTaskCall is the max number of times a task can be called.
	// This exists to prevent infinite loops on cyclic dependencies
	MaximumTaskCall = 100
)

// Executor executes a Taskfile
type Executor struct {
	Taskfile *taskfile.Taskfile

	Dir        string
	Entrypoint string
	Force      bool
	Watch      bool
	Verbose    bool
	Silent     bool
	Dry        bool
	Summary    bool
	Color      bool

	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer

	Logger      *logger.Logger
	Compiler    compiler.Compiler
	Output      output.Output
	OutputStyle string

	taskvars taskfile.Vars

	taskCallCount map[string]*int32
	mkdirMutexMap map[string]*sync.Mutex
}

// Run runs Task
func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
	// check if given tasks exist
	for _, c := range calls {
		if _, ok := e.Taskfile.Tasks[c.Task]; !ok {
			// FIXME: move to the main package
			e.PrintTasksHelp()
			return &taskNotFoundError{taskName: c.Task}
		}
	}

	if e.Summary {
		summary.PrintTasks(e.Logger, e.Taskfile, calls)
		return nil
	}

	if e.Watch {
		return e.watchTasks(calls...)
	}

	for _, c := range calls {
		if err := e.RunTask(ctx, c); err != nil {
			return err
		}
	}
	return nil
}

// Setup setups Executor's internal state
func (e *Executor) Setup() error {
	if e.Entrypoint == "" {
		e.Entrypoint = "Taskfile.yml"
	}

	var err error
	e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint)
	if err != nil {
		return err
	}
	e.taskvars, err = read.Taskvars(e.Dir)
	if err != nil {
		return err
	}

	if e.Stdin == nil {
		e.Stdin = os.Stdin
	}
	if e.Stdout == nil {
		e.Stdout = os.Stdout
	}
	if e.Stderr == nil {
		e.Stderr = os.Stderr
	}
	e.Logger = &logger.Logger{
		Stdout:  e.Stdout,
		Stderr:  e.Stderr,
		Verbose: e.Verbose,
		Color:   e.Color,
	}

	v, err := strconv.ParseFloat(e.Taskfile.Version, 64)
	if err != nil {
		return fmt.Errorf(`task: Could not parse taskfile version "%s": %v`, e.Taskfile.Version, err)
	}

	if v < 2 {
		return fmt.Errorf(`task: Taskfile version prior to v2 are not supported anymore`)
	}

	// consider as equal to the greater version if round
	if v == 2.0 {
		v = 2.6
	}

	if v > 3.0 {
		return fmt.Errorf(`task: Taskfile versions greater than v3.0 not implemented in the version of Task`)
	}

	// Color available only on v3
	if v < 3 {
		e.Logger.Color = false
	}

	e.Compiler = &compilerv2.CompilerV2{
		Dir:          e.Dir,
		Taskvars:     e.taskvars,
		TaskfileVars: e.Taskfile.Vars,
		Expansions:   e.Taskfile.Expansions,
		Logger:       e.Logger,
	}

	if v < 2.1 && e.Taskfile.Output != "" {
		return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
	}
	if v < 2.2 && len(e.Taskfile.Includes) > 0 {
		return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
	}

	if e.OutputStyle != "" {
		e.Taskfile.Output = e.OutputStyle
	}
	switch e.Taskfile.Output {
	case "", "interleaved":
		e.Output = output.Interleaved{}
	case "group":
		e.Output = output.Group{}
	case "prefixed":
		e.Output = output.Prefixed{}
	default:
		return fmt.Errorf(`task: output option "%s" not recognized`, e.Taskfile.Output)
	}

	if v <= 2.1 {
		err := errors.New(`task: Taskfile option "ignore_error" is only available starting on Taskfile version v2.1`)

		for _, task := range e.Taskfile.Tasks {
			if task.IgnoreError {
				return err
			}
			for _, cmd := range task.Cmds {
				if cmd.IgnoreError {
					return err
				}
			}
		}
	}

	if v < 2.6 {
		for _, task := range e.Taskfile.Tasks {
			if len(task.Preconditions) > 0 {
				return errors.New(`task: Task option "preconditions" is only available starting on Taskfile version v2.6`)
			}
		}
	}

	e.taskCallCount = make(map[string]*int32, len(e.Taskfile.Tasks))
	e.mkdirMutexMap = make(map[string]*sync.Mutex, len(e.Taskfile.Tasks))
	for k := range e.Taskfile.Tasks {
		e.taskCallCount[k] = new(int32)
		e.mkdirMutexMap[k] = &sync.Mutex{}
	}
	return nil
}

// RunTask runs a task by its name
func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
	t, err := e.CompiledTask(call)
	if err != nil {
		return err
	}
	if !e.Watch && atomic.AddInt32(e.taskCallCount[call.Task], 1) >= MaximumTaskCall {
		return &MaximumTaskCallExceededError{task: call.Task}
	}

	if err := e.runDeps(ctx, t); err != nil {
		return err
	}

	if !e.Force {
		preCondMet, err := e.areTaskPreconditionsMet(ctx, t)
		if err != nil {
			return err
		}

		upToDate, err := e.isTaskUpToDate(ctx, t)
		if err != nil {
			return err
		}

		if upToDate && preCondMet {
			if !e.Silent {
				e.Logger.Errf(logger.Magenta, `task: Task "%s" is up to date`, t.Task)
			}
			return nil
		}
	}

	if err := e.mkdir(t); err != nil {
		e.Logger.Errf(logger.Red, "task: cannot make directory %q: %v", t.Dir, err)
	}

	for i := range t.Cmds {
		if err := e.runCommand(ctx, t, call, i); err != nil {
			if err2 := e.statusOnError(t); err2 != nil {
				e.Logger.VerboseErrf(logger.Yellow, "task: error cleaning status on error: %v", err2)
			}

			if execext.IsExitError(err) && t.IgnoreError {
				e.Logger.VerboseErrf(logger.Yellow, "task: task error ignored: %v", err)
				continue
			}

			return &taskRunError{t.Task, err}
		}
	}
	return nil
}

func (e *Executor) mkdir(t *taskfile.Task) error {
	if t.Dir == "" {
		return nil
	}

	mutex := e.mkdirMutexMap[t.Task]
	mutex.Lock()
	defer mutex.Unlock()

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

func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
	g, ctx := errgroup.WithContext(ctx)

	for _, d := range t.Deps {
		d := d

		g.Go(func() error {
			err := e.RunTask(ctx, taskfile.Call{Task: d.Task, Vars: d.Vars})
			if err != nil {
				return err
			}
			return nil
		})
	}

	return g.Wait()
}

func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfile.Call, i int) error {
	cmd := t.Cmds[i]

	switch {
	case cmd.Task != "":
		err := e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
		if err != nil {
			return err
		}
		return nil
	case cmd.Cmd != "":
		if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) {
			e.Logger.Errf(logger.Green, "task: %s", cmd.Cmd)
		}

		if e.Dry {
			return nil
		}

		stdOut := e.Output.WrapWriter(e.Stdout, t.Prefix)
		stdErr := e.Output.WrapWriter(e.Stderr, t.Prefix)
		defer func() {
			if _, ok := stdOut.(*os.File); !ok {
				if closer, ok := stdOut.(io.Closer); ok {
					closer.Close()
				}
			}
			if _, ok := stdErr.(*os.File); !ok {
				if closer, ok := stdErr.(io.Closer); ok {
					closer.Close()
				}
			}
		}()

		err := execext.RunCommand(ctx, &execext.RunCommandOptions{
			Command: cmd.Cmd,
			Dir:     t.Dir,
			Env:     getEnviron(t),
			Stdin:   e.Stdin,
			Stdout:  stdOut,
			Stderr:  stdErr,
		})
		if execext.IsExitError(err) && cmd.IgnoreError {
			e.Logger.VerboseErrf(logger.Yellow, "task: command error ignored: %v", err)
			return nil
		}
		return err
	default:
		return nil
	}
}

func getEnviron(t *taskfile.Task) []string {
	if t.Env == nil {
		return nil
	}

	environ := os.Environ()
	for k, v := range t.Env.ToStringMap() {
		environ = append(environ, fmt.Sprintf("%s=%s", k, v))
	}
	return environ
}
<commit_msg>Fix error message<commit_after>package task

import (
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"strconv"
	"sync"
	"sync/atomic"

	"github.com/go-task/task/v2/internal/compiler"
	compilerv2 "github.com/go-task/task/v2/internal/compiler/v2"
	"github.com/go-task/task/v2/internal/execext"
	"github.com/go-task/task/v2/internal/logger"
	"github.com/go-task/task/v2/internal/output"
	"github.com/go-task/task/v2/internal/summary"
	"github.com/go-task/task/v2/internal/taskfile"
	"github.com/go-task/task/v2/internal/taskfile/read"

	"golang.org/x/sync/errgroup"
)

const (
	// MaximumTaskCall is the max number of times a task can be called.
	// This exists to prevent infinite loops on cyclic dependencies
	MaximumTaskCall = 100
)

// Executor executes a Taskfile
type Executor struct {
	Taskfile *taskfile.Taskfile

	Dir        string
	Entrypoint string
	Force      bool
	Watch      bool
	Verbose    bool
	Silent     bool
	Dry        bool
	Summary    bool
	Color      bool

	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer

	Logger      *logger.Logger
	Compiler    compiler.Compiler
	Output      output.Output
	OutputStyle string

	taskvars taskfile.Vars

	taskCallCount map[string]*int32
	mkdirMutexMap map[string]*sync.Mutex
}

// Run runs Task
func (e *Executor) Run(ctx context.Context, calls ...taskfile.Call) error {
	// check if given tasks exist
	for _, c := range calls {
		if _, ok := e.Taskfile.Tasks[c.Task]; !ok {
			// FIXME: move to the main package
			e.PrintTasksHelp()
			return &taskNotFoundError{taskName: c.Task}
		}
	}

	if e.Summary {
		summary.PrintTasks(e.Logger, e.Taskfile, calls)
		return nil
	}

	if e.Watch {
		return e.watchTasks(calls...)
	}

	for _, c := range calls {
		if err := e.RunTask(ctx, c); err != nil {
			return err
		}
	}
	return nil
}

// Setup setups Executor's internal state
func (e *Executor) Setup() error {
	if e.Entrypoint == "" {
		e.Entrypoint = "Taskfile.yml"
	}

	var err error
	e.Taskfile, err = read.Taskfile(e.Dir, e.Entrypoint)
	if err != nil {
		return err
	}
	e.taskvars, err = read.Taskvars(e.Dir)
	if err != nil {
		return err
	}

	if e.Stdin == nil {
		e.Stdin = os.Stdin
	}
	if e.Stdout == nil {
		e.Stdout = os.Stdout
	}
	if e.Stderr == nil {
		e.Stderr = os.Stderr
	}
	e.Logger = &logger.Logger{
		Stdout:  e.Stdout,
		Stderr:  e.Stderr,
		Verbose: e.Verbose,
		Color:   e.Color,
	}

	v, err := strconv.ParseFloat(e.Taskfile.Version, 64)
	if err != nil {
		return fmt.Errorf(`task: Could not parse taskfile version "%s": %v`, e.Taskfile.Version, err)
	}

	if v < 2 {
		return fmt.Errorf(`task: Taskfile versions prior to v2 are not supported anymore`)
	}

	// consider as equal to the greater version if round
	if v == 2.0 {
		v = 2.6
	}

	if v > 3.0 {
		return fmt.Errorf(`task: Taskfile versions greater than v3.0 not implemented in the version of Task`)
	}

	// Color available only on v3
	if v < 3 {
		e.Logger.Color = false
	}

	e.Compiler = &compilerv2.CompilerV2{
		Dir:          e.Dir,
		Taskvars:     e.taskvars,
		TaskfileVars: e.Taskfile.Vars,
		Expansions:   e.Taskfile.Expansions,
		Logger:       e.Logger,
	}

	if v < 2.1 && e.Taskfile.Output != "" {
		return fmt.Errorf(`task: Taskfile option "output" is only available starting on Taskfile version v2.1`)
	}
	if v < 2.2 && len(e.Taskfile.Includes) > 0 {
		return fmt.Errorf(`task: Including Taskfiles is only available starting on Taskfile version v2.2`)
	}

	if e.OutputStyle != "" {
		e.Taskfile.Output = e.OutputStyle
	}
	switch e.Taskfile.Output {
	case "", "interleaved":
		e.Output = output.Interleaved{}
	case "group":
		e.Output = output.Group{}
	case "prefixed":
		e.Output = output.Prefixed{}
	default:
		return fmt.Errorf(`task: output option "%s" not recognized`, e.Taskfile.Output)
	}

	if v <= 2.1 {
		err := errors.New(`task: Taskfile option "ignore_error" is only available starting on Taskfile version v2.1`)

		for _, task := range e.Taskfile.Tasks {
			if task.IgnoreError {
				return err
			}
			for _, cmd := range task.Cmds {
				if cmd.IgnoreError {
					return err
				}
			}
		}
	}

	if v < 2.6 {
		for _, task := range e.Taskfile.Tasks {
			if len(task.Preconditions) > 0 {
				return errors.New(`task: Task option "preconditions" is only available starting on Taskfile version v2.6`)
			}
		}
	}

	e.taskCallCount = make(map[string]*int32, len(e.Taskfile.Tasks))
	e.mkdirMutexMap = make(map[string]*sync.Mutex, len(e.Taskfile.Tasks))
	for k := range e.Taskfile.Tasks {
		e.taskCallCount[k] = new(int32)
		e.mkdirMutexMap[k] = &sync.Mutex{}
	}
	return nil
}

// RunTask runs a task by its name
func (e *Executor) RunTask(ctx context.Context, call taskfile.Call) error {
	t, err := e.CompiledTask(call)
	if err != nil {
		return err
	}
	if !e.Watch && atomic.AddInt32(e.taskCallCount[call.Task], 1) >= MaximumTaskCall {
		return &MaximumTaskCallExceededError{task: call.Task}
	}

	if err := e.runDeps(ctx, t); err != nil {
		return err
	}

	if !e.Force {
		preCondMet, err := e.areTaskPreconditionsMet(ctx, t)
		if err != nil {
			return err
		}

		upToDate, err := e.isTaskUpToDate(ctx, t)
		if err != nil {
			return err
		}

		if upToDate && preCondMet {
			if !e.Silent {
				e.Logger.Errf(logger.Magenta, `task: Task "%s" is up to date`, t.Task)
			}
			return nil
		}
	}

	if err := e.mkdir(t); err != nil {
		e.Logger.Errf(logger.Red, "task: cannot make directory %q: %v", t.Dir, err)
	}

	for i := range t.Cmds {
		if err := e.runCommand(ctx, t, call, i); err != nil {
			if err2 := e.statusOnError(t); err2 != nil {
				e.Logger.VerboseErrf(logger.Yellow, "task: error cleaning status on error: %v", err2)
			}

			if execext.IsExitError(err) && t.IgnoreError {
				e.Logger.VerboseErrf(logger.Yellow, "task: task error ignored: %v", err)
				continue
			}

			return &taskRunError{t.Task, err}
		}
	}
	return nil
}

func (e *Executor) mkdir(t *taskfile.Task) error {
	if t.Dir == "" {
		return nil
	}

	mutex := e.mkdirMutexMap[t.Task]
	mutex.Lock()
	defer mutex.Unlock()

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

func (e *Executor) runDeps(ctx context.Context, t *taskfile.Task) error {
	g, ctx := errgroup.WithContext(ctx)

	for _, d := range t.Deps {
		d := d

		g.Go(func() error {
			err := e.RunTask(ctx, taskfile.Call{Task: d.Task, Vars: d.Vars})
			if err != nil {
				return err
			}
			return nil
		})
	}

	return g.Wait()
}

func (e *Executor) runCommand(ctx context.Context, t *taskfile.Task, call taskfile.Call, i int) error {
	cmd := t.Cmds[i]

	switch {
	case cmd.Task != "":
		err := e.RunTask(ctx, taskfile.Call{Task: cmd.Task, Vars: cmd.Vars})
		if err != nil {
			return err
		}
		return nil
	case cmd.Cmd != "":
		if e.Verbose || (!cmd.Silent && !t.Silent && !e.Silent) {
			e.Logger.Errf(logger.Green, "task: %s", cmd.Cmd)
		}

		if e.Dry {
			return nil
		}

		stdOut := e.Output.WrapWriter(e.Stdout, t.Prefix)
		stdErr := e.Output.WrapWriter(e.Stderr, t.Prefix)
		defer func() {
			if _, ok := stdOut.(*os.File); !ok {
				if closer, ok := stdOut.(io.Closer); ok {
					closer.Close()
				}
			}
			if _, ok := stdErr.(*os.File); !ok {
				if closer, ok := stdErr.(io.Closer); ok {
					closer.Close()
				}
			}
		}()

		err := execext.RunCommand(ctx, &execext.RunCommandOptions{
			Command: cmd.Cmd,
			Dir:     t.Dir,
			Env:     getEnviron(t),
			Stdin:   e.Stdin,
			Stdout:  stdOut,
			Stderr:  stdErr,
		})
		if execext.IsExitError(err) && cmd.IgnoreError {
			e.Logger.VerboseErrf(logger.Yellow, "task: command error ignored: %v", err)
			return nil
		}
		return err
	default:
		return nil
	}
}

func getEnviron(t *taskfile.Task) []string {
	if t.Env == nil {
		return nil
	}

	environ := os.Environ()
	for k, v := range t.Env.ToStringMap() {
		environ = append(environ, fmt.Sprintf("%s=%s", k, v))
	}
	return environ
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/UniversityRadioYork/baps3-go"
)

type GetResponse struct {
	Status string
	Value  interface{}
}

func GetOk(value interface{}) *GetResponse {
	r := new(GetResponse)
	r.Status = "ok"
	r.Value = value
	return r
}

type bfConnector struct {
	conn   *baps3.Connector
	name   string
	wg     *sync.WaitGroup
	logger *log.Logger

	// Cache of BAPS3 service internal state
	state string
	time  time.Duration
	file  string

	reqCh chan httpRequest
	resCh <-chan baps3.Message

	// TODO(CaptainHayashi): move this away from baps3.Message to
	// something generic.
	updateCh chan<- baps3.Message
}

func initBfConnector(name string, updateCh chan baps3.Message, waitGroup *sync.WaitGroup, logger *log.Logger) (c *bfConnector) {
	resCh := make(chan baps3.Message)

	c = new(bfConnector)
	c.resCh = resCh
	c.conn = baps3.InitConnector(name, resCh, waitGroup, logger)
	c.name = name
	c.wg = waitGroup
	c.logger = logger
	c.reqCh = make(chan httpRequest)
	c.updateCh = updateCh

	return
}

func (c *bfConnector) Run() {
	defer c.wg.Done()
	defer close(c.conn.ReqCh)

	go c.conn.Run()

	fmt.Printf("connector %s now listening for requests\n", c.name)

	for {
		select {
		case rq, ok := <-c.reqCh:
			if !ok {
				return
			}

			// TODO(CaptainHayashi): probably make this more robust
			resource := strings.Replace(rq.resource, "/"+c.name, "", 1)
			fmt.Printf("connector %s response %s\n", c.name, resource)

			// TODO(CaptainHayashi): other methods
			rq.resCh <- c.get(resource)
		case res := <-c.resCh:
			var err error
			switch res.Word() {
			case baps3.RsFile:
				err = c.updateFileFromMessage(res)
			case baps3.RsState:
				err = c.updateStateFromMessage(res)
			case baps3.RsTime:
				err = c.updateTimeFromMessage(res)
			}
			if err != nil {
				fmt.Println(err)
			}
			c.updateCh <- res
		}
	}

	return
}

func splitResource(resource string) []string {
	res := strings.Split(strings.Trim(resource, "/"), "/")

	// The empty resource is returned as {""}: let's fix that
	if len(res) == 1 && res[0] == "" {
		res = []string{}
	}

	return res
}

func (c *bfConnector) get(resource string) interface{} {
	// TODO(CaptainHayashi): HTTP status codes

	resourcePath := splitResource(resource)

	if len(resourcePath) == 0 {
		return GetOk(c.rootGet())
	}

	var r interface{}

	switch resourcePath[0] {
	case "control":
		r = c.control(resourcePath[1:])
	case "player":
		r = c.player(resourcePath[1:])
		//case "playlist":
		//	r = c.playlist(resourcePath[1:])
	}

	if r == nil {
		// TODO(CaptainHayashi): more errors
		return GetResponse{
			Status: "what",
			Value:  "resource not found: " + resource,
		}
	}

	return GetOk(r)
}

// control is the main handler for the /control resource.
func (c *bfConnector) control(resourcePath []string) interface{} {
	if len(resourcePath) == 0 {
		return c.controlGet()
	}

	if len(resourcePath) == 1 {
		switch resourcePath[0] {
		case "state":
			return c.stateGet()
		}
	}

	return nil
}

// player is the main handler for the /player resource.
func (c *bfConnector) player(resourcePath []string) interface{} {
	if len(resourcePath) == 0 {
		return c.playerGet()
	}

	if len(resourcePath) == 1 {
		switch resourcePath[0] {
		case "time":
			return c.timeGet()
		case "file":
			return c.fileGet()
		}
	}

	return nil
}

// GET value for /
func (c *bfConnector) rootGet() interface{} {
	return struct {
		Control  interface{} `json:"control,omitempty"`
		Player   interface{} `json:"player,omitempty"`
		Playlist interface{} `json:"playlist,omitempty"`
	}{
		c.controlGet(),
		c.playerGet(),
		[]string{},
	}
}

// GET value for /control
func (c *bfConnector) controlGet() interface{} {
	return struct {
		State string `json:"state"`
	}{
		c.stateGet(),
	}
}

// GET value for /control/state
func (c *bfConnector) stateGet() string {
	return c.state
}

// GET value for /player
func (c *bfConnector) playerGet() interface{} {
	return struct {
		Time int64  `json:"time"`
		File string `json:"file,omitempty"`
	}{
		c.timeGet(),
		c.fileGet(),
	}
}

// GET value for /player/time
func (c *bfConnector) timeGet() int64 {
	// Time is reported in _micro_seconds
	return c.time.Nanoseconds() / 1000
}

// GET value for /player/file
func (c *bfConnector) fileGet() string {
	return c.file
}

func (c *bfConnector) updateFileFromMessage(res baps3.Message) (err error) {
	file, err := res.Arg(0)
	if err != nil {
		c.file = ""
		return
	}

	c.file = file

	return
}

func (c *bfConnector) updateStateFromMessage(res baps3.Message) (err error) {
	state, err := res.Arg(0)
	if err != nil {
		c.state = "???"
		return
	}

	c.state = state

	return
}

func (c *bfConnector) updateTimeFromMessage(res baps3.Message) (err error) {
	usecs, err := res.Arg(0)
	if err != nil {
		return
	}

	usec, err := strconv.Atoi(usecs)
	if err != nil {
		return
	}

	c.time = time.Duration(usec) * time.Microsecond

	return
}
<commit_msg>Add initial features struct.<commit_after>package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/UniversityRadioYork/baps3-go"
)

// TODO(CaptainHayashi): Petition for move to baps3-go

// Feature is the type for known feature flags.
type Feature uint8

const (
	// FileLoad represents the FileLoad standard feature.
	FileLoad Feature = iota
	// PlayStop represents the PlayStop standard feature.
	PlayStop
	// Seek represents the Seek standard feature.
	Seek
	// End represents the End standard feature.
	End
	// TimeReport represents the TimeReport standard feature.
	TimeReport
	// Playlist represents the Playlist standard feature.
	Playlist
	// PlaylistAutoAdvance represents the Playlist.AutoAdvance feature.
	PlaylistAutoAdvance
	// PlaylistTextItems represents the Playlist.TextItems feature.
	PlaylistTextItems
)

type GetResponse struct {
	Status string
	Value  interface{}
}

func GetOk(value interface{}) *GetResponse {
	r := new(GetResponse)
	r.Status = "ok"
	r.Value = value
	return r
}

type bfConnector struct {
	conn   *baps3.Connector
	name   string
	wg     *sync.WaitGroup
	logger *log.Logger

	// Cache of BAPS3 service internal state
	state string
	time  time.Duration
	file  string

	reqCh chan httpRequest
	resCh <-chan baps3.Message

	// TODO(CaptainHayashi): move this away from baps3.Message to
	// something generic.
	updateCh chan<- baps3.Message
}

func initBfConnector(name string, updateCh chan baps3.Message, waitGroup *sync.WaitGroup, logger *log.Logger) (c *bfConnector) {
	resCh := make(chan baps3.Message)

	c = new(bfConnector)
	c.resCh = resCh
	c.conn = baps3.InitConnector(name, resCh, waitGroup, logger)
	c.name = name
	c.wg = waitGroup
	c.logger = logger
	c.reqCh = make(chan httpRequest)
	c.updateCh = updateCh

	return
}

func (c *bfConnector) Run() {
	defer c.wg.Done()
	defer close(c.conn.ReqCh)

	go c.conn.Run()

	fmt.Printf("connector %s now listening for requests\n", c.name)

	for {
		select {
		case rq, ok := <-c.reqCh:
			if !ok {
				return
			}

			// TODO(CaptainHayashi): probably make this more robust
			resource := strings.Replace(rq.resource, "/"+c.name, "", 1)
			fmt.Printf("connector %s response %s\n", c.name, resource)

			// TODO(CaptainHayashi): other methods
			rq.resCh <- c.get(resource)
		case res := <-c.resCh:
			var err error
			switch res.Word() {
			case baps3.RsFile:
				err = c.updateFileFromMessage(res)
			case baps3.RsState:
				err = c.updateStateFromMessage(res)
			case baps3.RsTime:
				err = c.updateTimeFromMessage(res)
			}
			if err != nil {
				fmt.Println(err)
			}
			c.updateCh <- res
		}
	}

	return
}

func splitResource(resource string) []string {
	res := strings.Split(strings.Trim(resource, "/"), "/")

	// The empty resource is returned as {""}: let's fix that
	if len(res) == 1 && res[0] == "" {
		res = []string{}
	}

	return res
}

func (c *bfConnector) get(resource string) interface{} {
	// TODO(CaptainHayashi): HTTP status codes

	resourcePath := splitResource(resource)

	if len(resourcePath) == 0 {
		return GetOk(c.rootGet())
	}

	var r interface{}

	switch resourcePath[0] {
	case "control":
		r = c.control(resourcePath[1:])
	case "player":
		r = c.player(resourcePath[1:])
		//case "playlist":
		//	r = c.playlist(resourcePath[1:])
	}

	if r == nil {
		// TODO(CaptainHayashi): more errors
		return GetResponse{
			Status: "what",
			Value:  "resource not found: " + resource,
		}
	}

	return GetOk(r)
}

// control is the main handler for the /control resource.
func (c *bfConnector) control(resourcePath []string) interface{} {
	if len(resourcePath) == 0 {
		return c.controlGet()
	}

	if len(resourcePath) == 1 {
		switch resourcePath[0] {
		case "state":
			return c.stateGet()
		}
	}

	return nil
}

// player is the main handler for the /player resource.
func (c *bfConnector) player(resourcePath []string) interface{} {
	if len(resourcePath) == 0 {
		return c.playerGet()
	}

	if len(resourcePath) == 1 {
		switch resourcePath[0] {
		case "time":
			return c.timeGet()
		case "file":
			return c.fileGet()
		}
	}

	return nil
}

// GET value for /
func (c *bfConnector) rootGet() interface{} {
	return struct {
		Control  interface{} `json:"control,omitempty"`
		Player   interface{} `json:"player,omitempty"`
		Playlist interface{} `json:"playlist,omitempty"`
	}{
		c.controlGet(),
		c.playerGet(),
		[]string{},
	}
}

// GET value for /control
func (c *bfConnector) controlGet() interface{} {
	return struct {
		State string `json:"state"`
	}{
		c.stateGet(),
	}
}

// GET value for /control/state
func (c *bfConnector) stateGet() string {
	return c.state
}

// GET value for /player
func (c *bfConnector) playerGet() interface{} {
	return struct {
		Time int64  `json:"time"`
		File string `json:"file,omitempty"`
	}{
		c.timeGet(),
		c.fileGet(),
	}
}

// GET value for /player/time
func (c *bfConnector) timeGet() int64 {
	// Time is reported in _micro_seconds
	return c.time.Nanoseconds() / 1000
}

// GET value for /player/file
func (c *bfConnector) fileGet() string {
	return c.file
}

func (c *bfConnector) updateFileFromMessage(res baps3.Message) (err error) {
	file, err := res.Arg(0)
	if err != nil {
		c.file = ""
		return
	}

	c.file = file

	return
}

func (c *bfConnector) updateStateFromMessage(res baps3.Message) (err error) {
	state, err := res.Arg(0)
	if err != nil {
		c.state = "???"
		return
	}

	c.state = state

	return
}

func (c *bfConnector) updateTimeFromMessage(res baps3.Message) (err error) {
	usecs, err := res.Arg(0)
	if err != nil {
		return
	}

	usec, err := strconv.Atoi(usecs)
	if err != nil {
		return
	}

	c.time = time.Duration(usec) * time.Microsecond

	return
}
<|endoftext|>


<commit_before>package task

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	"github.com/BurntSushi/toml"
	"gopkg.in/yaml.v2"
)

var (
	// TaskFilePath is the default Taskfile
	TaskFilePath = "Taskfile"
	// ShExists is true if Bash was found
	ShExists bool
	// ShPath constains the Bash path if found
	ShPath string

	// Tasks constains the tasks parsed from Taskfile
	Tasks = make(map[string]*Task)

	runTasks = make(map[string]bool)
)

func init() {
	var err error
	ShPath, err = exec.LookPath("sh")
	if err != nil {
		return
	}
	ShExists = true
}

// Task represents a task
type Task struct {
	Cmds      []string
	Deps      []string
	Sources   []string
	Generates []string
	Dir       string
	Variables map[string]string
}

type taskNotFoundError struct {
	taskName string
}

func (err *taskNotFoundError) Error() string {
	return fmt.Sprintf(`Task "%s" not found`, err.taskName)
}

type taskRunError struct {
	taskName string
	err      error
}

func (err *taskRunError) Error() string {
	return fmt.Sprintf(`Failed to run task "%s": %v`, err.taskName, err.err)
}

// Run runs Task
func Run() {
	log.SetFlags(0)

	args := os.Args[1:]
	if len(args) == 0 {
		log.Fatal("No argument given")
	}

	var err error
	Tasks, err = readTaskfile()
	if err != nil {
		log.Fatal(err)
	}

	for _, a := range args {
		if err = RunTask(a); err != nil {
			log.Fatal(err)
		}
	}
}

// RunTask runs a task by its name
func RunTask(name string) error {
	if _, found := runTasks[name]; found {
		return &taskRunError{taskName: name, err: fmt.Errorf("Cyclic dependency detected")}
	}
	runTasks[name] = true

	t, ok := Tasks[name]
	if !ok {
		return &taskNotFoundError{name}
	}

	if isTaskUpToDate(t) {
		log.Printf(`Task "%s" is up to date`, name)
		return nil
	}

	vars := t.handleVariables()

	for _, d := range t.Deps {
		if err := RunTask(ReplaceVariables(d, vars)); err != nil {
			return err
		}
	}

	for _, c := range t.Cmds {
		if err := runCommand(ReplaceVariables(c, vars), ReplaceVariables(t.Dir, vars)); err != nil {
			return &taskRunError{name, err}
		}
	}
	return nil
}

func isTaskUpToDate(t *Task) bool {
	if len(t.Sources) == 0 || len(t.Generates) == 0 {
		return false
	}

	sourcesMaxTime, err := getPatternsMaxTime(t.Sources)
	if err != nil || sourcesMaxTime.IsZero() {
		return false
	}

	generatesMinTime, err := getPatternsMinTime(t.Generates)
	if err != nil || generatesMinTime.IsZero() {
		return false
	}

	return generatesMinTime.After(sourcesMaxTime)
}

func runCommand(c, path string) error {
	var cmd *exec.Cmd
	if ShExists {
		cmd = exec.Command(ShPath, "-c", c)
	} else {
		cmd = exec.Command("cmd", "/C", c)
	}
	if path != "" {
		cmd.Dir = path
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return err
	}
	return nil
}

func readTaskfile() (tasks map[string]*Task, err error) {
	if b, err := ioutil.ReadFile(TaskFilePath + ".yml"); err == nil {
		return tasks, yaml.Unmarshal(b, &tasks)
	}
	if b, err := ioutil.ReadFile(TaskFilePath + ".json"); err == nil {
		return tasks, json.Unmarshal(b, &tasks)
	}
	if b, err := ioutil.ReadFile(TaskFilePath + ".toml"); err == nil {
		return tasks, toml.Unmarshal(b, &tasks)
	}
	return nil, ErrNoTaskFile
}

// ErrNoTaskFile is returns when the program can not find a proper TaskFile
var ErrNoTaskFile = errors.New("no task file found (is it named '" + TaskFilePath + "'?)")
<commit_msg>Handling errors on variable handling<commit_after>package task

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	"github.com/BurntSushi/toml"
	"gopkg.in/yaml.v2"
)

var (
	// TaskFilePath is the default Taskfile
	TaskFilePath = "Taskfile"
	// ShExists is true if Bash was found
	ShExists bool
	// ShPath constains the Bash path if found
	ShPath string

	// Tasks constains the tasks parsed from Taskfile
	Tasks = make(map[string]*Task)

	runTasks = make(map[string]bool)
)

func init() {
	var err error
	ShPath, err = exec.LookPath("sh")
	if err != nil {
		return
	}
	ShExists = true
}

// Task represents a task
type Task struct {
	Cmds      []string
	Deps      []string
	Sources   []string
	Generates []string
	Dir       string
	Variables map[string]string
}

type taskNotFoundError struct {
	taskName string
}

func (err *taskNotFoundError) Error() string {
	return fmt.Sprintf(`Task "%s" not found`, err.taskName)
}

type taskRunError struct {
	taskName string
	err      error
}

func (err *taskRunError) Error() string {
	return fmt.Sprintf(`Failed to run task "%s": %v`, err.taskName, err.err)
}

// Run runs Task
func Run() {
	log.SetFlags(0)

	args := os.Args[1:]
	if len(args) == 0 {
		log.Fatal("No argument given")
	}

	var err error
	Tasks, err = readTaskfile()
	if err != nil {
		log.Fatal(err)
	}

	for _, a := range args {
		if err = RunTask(a); err != nil {
			log.Fatal(err)
		}
	}
}

// RunTask runs a task by its name
func RunTask(name string) error {
	if _, found := runTasks[name]; found {
		return &taskRunError{taskName: name, err: fmt.Errorf("Cyclic dependency detected")}
	}
	runTasks[name] = true

	t, ok := Tasks[name]
	if !ok {
		return &taskNotFoundError{name}
	}

	if isTaskUpToDate(t) {
		log.Printf(`Task "%s" is up to date`, name)
		return nil
	}

	vars, err := t.handleVariables()
	if err != nil {
		return &taskRunError{name, err}
	}

	for _, d := range t.Deps {
		if err := RunTask(ReplaceVariables(d, vars)); err != nil {
			return err
		}
	}

	for _, c := range t.Cmds {
		if err := runCommand(ReplaceVariables(c, vars), ReplaceVariables(t.Dir, vars)); err != nil {
			return &taskRunError{name, err}
		}
	}
	return nil
}

func isTaskUpToDate(t *Task) bool {
	if len(t.Sources) == 0 || len(t.Generates) == 0 {
		return false
	}

	sourcesMaxTime, err := getPatternsMaxTime(t.Sources)
	if err != nil || sourcesMaxTime.IsZero() {
		return false
	}

	generatesMinTime, err := getPatternsMinTime(t.Generates)
	if err != nil || generatesMinTime.IsZero() {
		return false
	}

	return generatesMinTime.After(sourcesMaxTime)
}

func runCommand(c, path string) error {
	var cmd *exec.Cmd
	if ShExists {
		cmd = exec.Command(ShPath, "-c", c)
	} else {
		cmd = exec.Command("cmd", "/C", c)
	}
	if path != "" {
		cmd.Dir = path
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		return err
	}
	return nil
}

func readTaskfile() (tasks map[string]*Task, err error) {
	if b, err := ioutil.ReadFile(TaskFilePath + ".yml"); err == nil {
		return tasks, yaml.Unmarshal(b, &tasks)
	}
	if b, err := ioutil.ReadFile(TaskFilePath + ".json"); err == nil {
		return tasks, json.Unmarshal(b, &tasks)
	}
	if b, err := ioutil.ReadFile(TaskFilePath + ".toml"); err == nil {
		return tasks, toml.Unmarshal(b, &tasks)
	}
	return nil, ErrNoTaskFile
}

// ErrNoTaskFile is returns when the program can not find a proper TaskFile
var ErrNoTaskFile = errors.New("no task file found (is it named '" + TaskFilePath + "'?)")
<|endoftext|>


<commit_before>package test

import (
	"bytes"
	"errors"
	"fmt"
	"math"
	"runtime"
	"strings"
	"testing"
)

// ErrPlain is the default error that is returned for functions in this package.
var ErrPlain = errors.New("error")

////////////////////////////////////////////////////////////////

func fileline(i int) string {
	_, file, line, ok := runtime.Caller(i)
	if !ok {
		return ""
	}
	parts := strings.Split(file, "/")
	file = parts[len(parts)-1]
	return fmt.Sprintf("%s:%d", file, line)
}

func trace() string {
	trace2 := fileline(2)
	trace3 := fileline(3)
	return "\r\t" + strings.Repeat(" ", len(fmt.Sprintf("%s:", trace2))) + "\r\t" + trace3
}

func message(msgs ...interface{}) string {
	if len(msgs) == 0 {
		return "\n"
	}
	return ": " + fmt.Sprintln(msgs...)
}

func printable(s string) string {
	s = strings.Replace(s, "\n", `\n`, -1)
	s = strings.Replace(s, "\r", `\r`, -1)
	s = strings.Replace(s, "\t", `\t`, -1)
	return s
}

/////////////////////////////////////////////////////////////////

func That(t *testing.T, condition bool, msgs ...interface{}) {
	if !condition {
		t.Errorf("%s%s", trace(), message(msgs...))
	}
}

func Error(t *testing.T, err, expected error, msgs ...interface{}) {
	if err != expected {
		t.Errorf("%s%s   error: %v\nexpected: %v\n", trace(), message(msgs...), err, expected)
	}
}

func Int(t *testing.T, output, expected int, msgs ...interface{}) {
	if output != expected {
		t.Errorf("%s%s  output: %d\nexpected: %d\n", trace(), message(msgs...), output, expected)
	}
}

func Float(t *testing.T, output, expected float64, msgs ...interface{}) {
	if math.Abs(output-expected) > 1e-10 {
		t.Errorf("%s%s  output: %f\nexpected: %f\n", trace(), message(msgs...), output, expected)
	}
}

func String(t *testing.T, output, expected string, msgs ...interface{}) {
	if output != expected {
		t.Errorf("%s%s  output: %s\nexpected: %s\n", trace(), message(msgs...), printable(output), printable(expected))
	}
}

func Bytes(t *testing.T, output, expected []byte, msgs ...interface{}) {
	if !bytes.Equal(output, expected) {
		t.Errorf("%s%s  output: %s\nexpected: %s\n", trace(), message(msgs...), printable(string(output)), printable(string(expected)))
	}
}

func Minify(t *testing.T, input string, err error, output, expected string, msgs ...interface{}) {
	if err != nil {
		t.Errorf("%s%s   given: %s\n   error: %v\n", trace(), message(msgs...), printable(input), err)
	}
	if output != expected {
		t.Errorf("%s%s   given: %s\n  output: %s\nexpected: %s\n", trace(), message(msgs...), printable(input), printable(output), printable(expected))
	}
}
<commit_msg>Add test V for two interfaces<commit_after>package test

import (
	"bytes"
	"errors"
	"fmt"
	"math"
	"reflect"
	"runtime"
	"strings"
	"testing"
)

// ErrPlain is the default error that is returned for functions in this package.
var ErrPlain = errors.New("error")

////////////////////////////////////////////////////////////////

func fileline(i int) string {
	_, file, line, ok := runtime.Caller(i)
	if !ok {
		return ""
	}
	parts := strings.Split(file, "/")
	file = parts[len(parts)-1]
	return fmt.Sprintf("%s:%d", file, line)
}

func trace() string {
	trace2 := fileline(2)
	trace3 := fileline(3)
	return "\r\t" + strings.Repeat(" ", len(fmt.Sprintf("%s:", trace2))) + "\r\t" + trace3
}

func message(msgs ...interface{}) string {
	if len(msgs) == 0 {
		return "\n"
	}
	return ": " + fmt.Sprintln(msgs...)
}

func printable(s string) string {
	s = strings.Replace(s, "\n", `\n`, -1)
	s = strings.Replace(s, "\r", `\r`, -1)
	s = strings.Replace(s, "\t", `\t`, -1)
	return s
}

const (
	Red   = "31"
	Green = "32"
)

func color(color string, s interface{}) string {
	return fmt.Sprintf("\033[00;%sm%v\033[00m", color, s)
}

/////////////////////////////////////////////////////////////////

func That(t *testing.T, condition bool, msgs ...interface{}) {
	if !condition {
		t.Errorf("%s%s", trace(), message(msgs...))
	}
}

func V(t *testing.T, context string, got, wanted interface{}) {
	gotType := reflect.TypeOf(got)
	wantedType := reflect.TypeOf(wanted)
	if gotType != wantedType {
		t.Errorf("%s: %s: type %v != %v", trace(), context, color(Red, gotType), color(Green, wantedType))
	}
	if got != wanted {
		t.Errorf("%s: %s: %v != %v", trace(), context, color(Red, got), color(Green, wanted))
	}
}

func Error(t *testing.T, err, expected error, msgs ...interface{}) {
	if err != expected {
		t.Errorf("%s%s   error: %v\nexpected: %v\n", trace(), message(msgs...), err, expected)
	}
}

func Int(t *testing.T, output, expected int, msgs ...interface{}) {
	if output != expected {
		t.Errorf("%s%s  output: %d\nexpected: %d\n", trace(), message(msgs...), output, expected)
	}
}

func Float(t *testing.T, output, expected float64, msgs ...interface{}) {
	if math.Abs(output-expected) > 1e-10 {
		t.Errorf("%s%s  output: %f\nexpected: %f\n", trace(), message(msgs...), output, expected)
	}
}

func String(t *testing.T, output, expected string, msgs ...interface{}) {
	if output != expected {
		t.Errorf("%s%s  output: %s\nexpected: %s\n", trace(), message(msgs...), printable(output), printable(expected))
	}
}

func Bytes(t *testing.T, output, expected []byte, msgs ...interface{}) {
	if !bytes.Equal(output, expected) {
		t.Errorf("%s%s  output: %s\nexpected: %s\n", trace(), message(msgs...), printable(string(output)), printable(string(expected)))
	}
}

func Minify(t *testing.T, input string, err error, output, expected string, msgs ...interface{}) {
	if err != nil {
		t.Errorf("%s%s   given: %s\n   error: %v\n", trace(), message(msgs...), printable(input), err)
	}
	if output != expected {
		t.Errorf("%s%s   given: %s\n  output: %s\nexpected: %s\n", trace(), message(msgs...), printable(input), printable(output), printable(expected))
	}
}
<|endoftext|>


<commit_before>package main

import (
	"./mysql";
	"fmt";
	"os";
)

func main() {
	dbh, err := mysql.Connect("127.0.0.1:3306", "test", "test", "predb");
	if err != nil {
		fmt.Printf("%s\n", err);
		os.Exit(1);
	}
	fmt.Printf("Connected to %s\n", dbh.ServerVersion);
	_, err = dbh.Query("SELECT * FROM releases LIMIT 1000");

	for row := dbh.FetchRow(); row != nil; row = dbh.FetchRow() {
		for i := 0; i < len(row.Data); i++ {
			fmt.Printf("%s\t", dbh.CurrentResultSet.Fields[i])
		}
		fmt.Printf("\n");
		for i := 0; i < len(row.Data); i++ {
			fmt.Printf("%s\t", row.Data[i])
		}
		fmt.Printf("\n");
		if err != nil {
			fmt.Printf("%s\n", err);
			os.Exit(1);
		}
	}
	dbh.Quit();
}
<commit_msg>Test insert and delete<commit_after>package main

import (
	"./mysql";
	"fmt";
	"os";
)

func main() {
	dbh, err := mysql.Connect("127.0.0.1:3306", "test", "test", "test");
	if err != nil {
		fmt.Printf("%s\n", err);
		os.Exit(1);
	}
	fmt.Printf("Connected to %s\n", dbh.ServerVersion);
	res := new(mysql.MySQLResponse);
//	res, err = dbh.Query("SELECT * FROM releases LIMIT 1000");
	res, err = dbh.Query("INSERT INTO test (sha1) VALUES(SHA1('foo'))");
	fmt.Printf("%s\n", res);
	if err != nil {
		fmt.Printf("%s\n", err);
		os.Exit(1);
	}
	res, err = dbh.Query(fmt.Sprintf("DELETE FROM test WHERE id=%d", res.InsertId));
	fmt.Printf("%s\n", res);
/*
	for row := dbh.FetchRow(); row != nil; row = dbh.FetchRow() {
		for i := 0; i < len(row.Data); i++ {
			fmt.Printf("%s\t", dbh.CurrentResultSet.Fields[i])
		}
		fmt.Printf("\n");
		for i := 0; i < len(row.Data); i++ {
			fmt.Printf("%s\t", row.Data[i])
		}
		fmt.Printf("\n");
		if err != nil {
			fmt.Printf("%s\n", err);
			os.Exit(1);
		}
	}
*/
	dbh.Quit();
}
<|endoftext|>


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

package docker

import (
	"encoding/json"
	"fmt"
	"github.com/dotcloud/docker"
	"io"
	"net/http"
	"os"
)

// ListContainersOptions specify parameters to the ListContainers function.
//
// See http://goo.gl/QpCnDN for more details.
type ListContainersOptions struct {
	All    bool
	Size   bool
	Limit  int
	Since  string
	Before string
}

// ListContainers returns a slice of containers matching the given criteria.
//
// See http://goo.gl/QpCnDN for more details.
func (c *Client) ListContainers(opts ListContainersOptions) ([]docker.APIContainers, error) {
	path := "/containers/json?" + queryString(opts)
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var containers []docker.APIContainers
	err = json.Unmarshal(body, &containers)
	if err != nil {
		return nil, err
	}
	return containers, nil
}

// InspectContainer returns information about a container by its ID.
//
// See http://goo.gl/2o52Sx for more details.
func (c *Client) InspectContainer(id string) (*docker.Container, error) {
	path := "/containers/" + id + "/json"
	body, status, err := c.do("GET", path, nil)
	if status == http.StatusNotFound {
		return nil, &NoSuchContainer{ID: id}
	}
	if err != nil {
		return nil, err
	}
	var container docker.Container
	err = json.Unmarshal(body, &container)
	if err != nil {
		return nil, err
	}
	return &container, nil
}

// CreateContainer creates a new container, returning the container instance,
// or an error in case of failure.
//
// See http://goo.gl/tjihUc for more details.
func (c *Client) CreateContainer(config *docker.Config) (*docker.Container, error) {
	body, status, err := c.do("POST", "/containers/create", config)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}
	var container docker.Container
	err = json.Unmarshal(body, &container)
	if err != nil {
		return nil, err
	}
	return &container, nil
}

// StartContainer starts a container, returning an errror in case of failure.
//
// See http://goo.gl/y5GZlE for more details.
func (c *Client) StartContainer(id string) error {
	path := "/containers/" + id + "/start"
	hostConfig := &docker.HostConfig{}
	_, status, err := c.do("POST", path, hostConfig)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// StopContainer stops a container, killing it after the given timeout (in
// seconds).
//
// See http://goo.gl/X2mj8t for more details.
func (c *Client) StopContainer(id string, timeout uint) error {
	path := fmt.Sprintf("/containers/%s/stop?t=%d", id, timeout)
	_, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// RestartContainer stops a container, killing it after the given timeout (in
// seconds), during the stop process.
//
// See http://goo.gl/zms73Z for more details.
func (c *Client) RestartContainer(id string, timeout uint) error {
	path := fmt.Sprintf("/containers/%s/restart?t=%d", id, timeout)
	_, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// KillContainer kills a container, returning an error in case of failure.
//
// See http://goo.gl/DPbbBy for more details.
func (c *Client) KillContainer(id string) error {
	path := "/containers/" + id + "/kill"
	_, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// RemoveContainer removes a container, returning an error in case of failure.
//
// See http://goo.gl/PBvGdU for more details.
func (c *Client) RemoveContainer(id string) error {
	_, status, err := c.do("DELETE", "/containers/"+id, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// WaitContainer blocks until the given container stops, return the exit code
// of the container status.
//
// See http://goo.gl/gnHJL2 for more details.
func (c *Client) WaitContainer(id string) (int, error) {
	body, status, err := c.do("POST", "/containers/"+id+"/wait", nil)
	if status == http.StatusNotFound {
		return 0, &NoSuchContainer{ID: id}
	}
	if err != nil {
		return 0, err
	}
	var r struct{ StatusCode int }
	err = json.Unmarshal(body, &r)
	if err != nil {
		return 0, err
	}
	return r.StatusCode, nil
}

// CommitContainerOptions aggregates parameters to the CommitContainer method.
//
// See http://goo.gl/628gxm for more details.
type CommitContainerOptions struct {
	Container  string
	Repository string `qs:"repo"`
	Tag        string
	Message    string `qs:"m"`
	Author     string
	Run        *docker.Config
}

// CommitContainer creates a new image from a container's changes.
//
// See http://goo.gl/628gxm for more details.
func (c *Client) CommitContainer(opts CommitContainerOptions) (*docker.Image, error) {
	path := "/commit?" + queryString(opts)
	body, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return nil, &NoSuchContainer{ID: opts.Container}
	}
	if err != nil {
		return nil, err
	}
	var image docker.Image
	err = json.Unmarshal(body, &image)
	if err != nil {
		return nil, err
	}
	return &image, nil
}

// AttachToContainerOptions is the set of options that can be used when
// attaching to a container.
//
// See http://goo.gl/oPzcqH for more details.
type AttachToContainerOptions struct {
	Container    string
	InputFile    *os.File
	OutputStream io.Writer
	ErrorStream  io.Writer
	RawTerminal  bool

	// Get container logs, sending it to OutputStream.
	Logs bool

	// Stream the response?
	Stream bool

	// Attach to stdin, and use InputFile.
	Stdin bool

	// Attach to stdout, and use OutputStream.
	Stdout bool

	// Attach to stderr, and use ErrorStream.
	Stderr bool
}

// AttachToContainer attaches to a container, using the given options.
//
// See http://goo.gl/oPzcqH for more details.
func (c *Client) AttachToContainer(opts AttachToContainerOptions) error {
	container := opts.Container
	if container == "" {
		return &NoSuchContainer{ID: container}
	}
	stdout := opts.OutputStream
	stderr := opts.ErrorStream
	stdin := opts.InputFile
	raw := opts.RawTerminal
	opts.Container = ""
	opts.InputFile = nil
	opts.OutputStream = nil
	opts.ErrorStream = nil
	opts.RawTerminal = false
	path := "/containers/" + container + "/attach?" + queryString(opts)
	return c.hijack("POST", path, raw, stdin, stderr, stdout)
}

// ExportContainer export the contents of container id as tar archive
// and prints the exported contents to stdout.
//
// see http://goo.gl/Lqk0FZ for more details.
func (c *Client) ExportContainer(id string, out io.Writer) error {
	if id == "" {
		return NoSuchContainer{ID: id}
	}
	url := fmt.Sprintf("/containers/%s/export", id)
	return c.stream("GET", url, nil, out)
}

// NoSuchContainer is the error returned when a given container does not exist.
type NoSuchContainer struct {
	ID string
}

func (err NoSuchContainer) Error() string {
	return "No such container: " + err.ID
}
<commit_msg>allow StartContainer to accept bind mounts<commit_after>// Copyright 2013 Francisco Souza. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package docker

import (
	"encoding/json"
	"fmt"
	"github.com/dotcloud/docker"
	"io"
	"net/http"
	"os"
)

// ListContainersOptions specify parameters to the ListContainers function.
//
// See http://goo.gl/QpCnDN for more details.
type ListContainersOptions struct {
	All    bool
	Size   bool
	Limit  int
	Since  string
	Before string
}

// ListContainers returns a slice of containers matching the given criteria.
//
// See http://goo.gl/QpCnDN for more details.
func (c *Client) ListContainers(opts ListContainersOptions) ([]docker.APIContainers, error) {
	path := "/containers/json?" + queryString(opts)
	body, _, err := c.do("GET", path, nil)
	if err != nil {
		return nil, err
	}
	var containers []docker.APIContainers
	err = json.Unmarshal(body, &containers)
	if err != nil {
		return nil, err
	}
	return containers, nil
}

// InspectContainer returns information about a container by its ID.
//
// See http://goo.gl/2o52Sx for more details.
func (c *Client) InspectContainer(id string) (*docker.Container, error) {
	path := "/containers/" + id + "/json"
	body, status, err := c.do("GET", path, nil)
	if status == http.StatusNotFound {
		return nil, &NoSuchContainer{ID: id}
	}
	if err != nil {
		return nil, err
	}
	var container docker.Container
	err = json.Unmarshal(body, &container)
	if err != nil {
		return nil, err
	}
	return &container, nil
}

// CreateContainer creates a new container, returning the container instance,
// or an error in case of failure.
//
// See http://goo.gl/tjihUc for more details.
func (c *Client) CreateContainer(config *docker.Config) (*docker.Container, error) {
	body, status, err := c.do("POST", "/containers/create", config)
	if status == http.StatusNotFound {
		return nil, ErrNoSuchImage
	}
	if err != nil {
		return nil, err
	}
	var container docker.Container
	err = json.Unmarshal(body, &container)
	if err != nil {
		return nil, err
	}
	return &container, nil
}

// StartContainer starts a container, returning an errror in case of failure.
//
// See http://goo.gl/y5GZlE for more details.
func (c *Client) StartContainer(id string, hostConfig *docker.HostConfig) error {
	path := "/containers/" + id + "/start"
	_, status, err := c.do("POST", path, hostConfig)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// StopContainer stops a container, killing it after the given timeout (in
// seconds).
//
// See http://goo.gl/X2mj8t for more details.
func (c *Client) StopContainer(id string, timeout uint) error {
	path := fmt.Sprintf("/containers/%s/stop?t=%d", id, timeout)
	_, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// RestartContainer stops a container, killing it after the given timeout (in
// seconds), during the stop process.
//
// See http://goo.gl/zms73Z for more details.
func (c *Client) RestartContainer(id string, timeout uint) error {
	path := fmt.Sprintf("/containers/%s/restart?t=%d", id, timeout)
	_, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// KillContainer kills a container, returning an error in case of failure.
//
// See http://goo.gl/DPbbBy for more details.
func (c *Client) KillContainer(id string) error {
	path := "/containers/" + id + "/kill"
	_, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// RemoveContainer removes a container, returning an error in case of failure.
//
// See http://goo.gl/PBvGdU for more details.
func (c *Client) RemoveContainer(id string) error {
	_, status, err := c.do("DELETE", "/containers/"+id, nil)
	if status == http.StatusNotFound {
		return &NoSuchContainer{ID: id}
	}
	if err != nil {
		return err
	}
	return nil
}

// WaitContainer blocks until the given container stops, return the exit code
// of the container status.
//
// See http://goo.gl/gnHJL2 for more details.
func (c *Client) WaitContainer(id string) (int, error) {
	body, status, err := c.do("POST", "/containers/"+id+"/wait", nil)
	if status == http.StatusNotFound {
		return 0, &NoSuchContainer{ID: id}
	}
	if err != nil {
		return 0, err
	}
	var r struct{ StatusCode int }
	err = json.Unmarshal(body, &r)
	if err != nil {
		return 0, err
	}
	return r.StatusCode, nil
}

// CommitContainerOptions aggregates parameters to the CommitContainer method.
//
// See http://goo.gl/628gxm for more details.
type CommitContainerOptions struct {
	Container  string
	Repository string `qs:"repo"`
	Tag        string
	Message    string `qs:"m"`
	Author     string
	Run        *docker.Config
}

// CommitContainer creates a new image from a container's changes.
//
// See http://goo.gl/628gxm for more details.
func (c *Client) CommitContainer(opts CommitContainerOptions) (*docker.Image, error) {
	path := "/commit?" + queryString(opts)
	body, status, err := c.do("POST", path, nil)
	if status == http.StatusNotFound {
		return nil, &NoSuchContainer{ID: opts.Container}
	}
	if err != nil {
		return nil, err
	}
	var image docker.Image
	err = json.Unmarshal(body, &image)
	if err != nil {
		return nil, err
	}
	return &image, nil
}

// AttachToContainerOptions is the set of options that can be used when
// attaching to a container.
//
// See http://goo.gl/oPzcqH for more details.
type AttachToContainerOptions struct {
	Container    string
	InputFile    *os.File
	OutputStream io.Writer
	ErrorStream  io.Writer
	RawTerminal  bool

	// Get container logs, sending it to OutputStream.
	Logs bool

	// Stream the response?
	Stream bool

	// Attach to stdin, and use InputFile.
	Stdin bool

	// Attach to stdout, and use OutputStream.
	Stdout bool

	// Attach to stderr, and use ErrorStream.
	Stderr bool
}

// AttachToContainer attaches to a container, using the given options.
//
// See http://goo.gl/oPzcqH for more details.
func (c *Client) AttachToContainer(opts AttachToContainerOptions) error {
	container := opts.Container
	if container == "" {
		return &NoSuchContainer{ID: container}
	}
	stdout := opts.OutputStream
	stderr := opts.ErrorStream
	stdin := opts.InputFile
	raw := opts.RawTerminal
	opts.Container = ""
	opts.InputFile = nil
	opts.OutputStream = nil
	opts.ErrorStream = nil
	opts.RawTerminal = false
	path := "/containers/" + container + "/attach?" + queryString(opts)
	return c.hijack("POST", path, raw, stdin, stderr, stdout)
}

// ExportContainer export the contents of container id as tar archive
// and prints the exported contents to stdout.
//
// see http://goo.gl/Lqk0FZ for more details.
func (c *Client) ExportContainer(id string, out io.Writer) error {
	if id == "" {
		return NoSuchContainer{ID: id}
	}
	url := fmt.Sprintf("/containers/%s/export", id)
	return c.stream("GET", url, nil, out)
}

// NoSuchContainer is the error returned when a given container does not exist.
type NoSuchContainer struct {
	ID string
}

func (err NoSuchContainer) Error() string {
	return "No such container: " + err.ID
}
<|endoftext|>


<commit_before>package qp

import (
	"encoding"
	"encoding/binary"
	"errors"
	"io"
	"sync"
)

var (
	// ErrPayloadTooShort indicates that the message was not complete.
	ErrPayloadTooShort = errors.New("payload too short")

	// ErrMessageTooBig indicates that the message, when encoded and wrapped in
	// container, does not fit in the configured message size.
	ErrMessageTooBig = errors.New("message size larger than buffer")
)

// Protocol defines a protocol message encoder/decoder
type Protocol interface {
	MessageType(Message) (MessageType, error)
	Message(MessageType) (Message, error)
}

// Default is the protocol used by the raw Encode and Decode functions.
var Default = NineP2000

// MessageType is the type of the contained message.
type MessageType byte

// Message is an interface describing an item that can encode itself to a
// writer, decode itself from a reader. It is also capable of getting the
// message tag, which is merely a convenience feature to save a type assert
// for access to the tag.
type Message interface {
	encoding.BinaryUnmarshaler
	encoding.BinaryMarshaler
	GetTag() Tag
}

// write writes all the provided data unless an error occurs.
func write(w io.Writer, b []byte) error {
	var (
		written int
		err     error
		l       = len(b)
	)
	for written < l {
		written, err = w.Write(b[written:])
		if err != nil {
			return err
		}
	}

	return nil
}

// Encoder handles writes encoded messages to an io.Writer.
type Encoder struct {
	// Protocol is the protocol codec used for encoding messages.
	Protocol Protocol

	// Writer is the writer to encode messages to.
	Writer io.Writer

	// MessageSize is the maximum message size negotiated for the protocol. It
	// is used to enforce a limit on writes.
	MessageSize uint32

	// writeLock is used to synchronize writes. Without it, messages would end
	// up interleaved and incomprehensible.
	writeLock sync.Mutex
}

// WriteMessage encodes a message and writes it to the Encoders associated
// io.Writer.
func (e *Encoder) WriteMessage(m Message) error {
	var (
		mt             MessageType
		msgbuf, header []byte
		err            error
	)

	if mt, err = e.Protocol.MessageType(m); err != nil {
		return err
	}

	if msgbuf, err = m.MarshalBinary(); err != nil {
		return err
	}

	if len(msgbuf)+HeaderSize > int(e.MessageSize) {
		return ErrMessageTooBig
	}

	header = make([]byte, HeaderSize)
	binary.LittleEndian.PutUint32(header[0:4], uint32(len(msgbuf)+HeaderSize))
	header[4] = byte(mt)

	e.writeLock.Lock()
	defer e.writeLock.Unlock()

	if err = write(e.Writer, header); err != nil {
		return err
	}

	if err = write(e.Writer, msgbuf); err != nil {
		return err
	}

	return nil
}

// Decoder reads messages from an io.Reader, calling a callback for each of them.
// message. Unlike Codec.Decode,
type Decoder struct {
	// Protocol is the protocol codec used for decoding messages.
	Protocol Protocol

	// Reader is the reader to decode from.
	Reader io.Reader

	// Greedy enables greedy decoding, which is whether or not the decoder
	// should try to read more than just the next message into the buffer.
	// This can save significant amount of Read calls, but must not be set if
	// the user intents to change the reader soon, as it may result in losing
	// a partial read. A common thing to do would be to enable Greedy after
	// protocol negotiation.
	Greedy bool

	// MessageSize is the maximum message size negotiated for the protocol. It
	// is used to allocate the decoding buffer.
	MessageSize uint32

	// total is the count of bytes in the buffer. It is used to keep track
	// of buffer usage (read offset and cleanup), and is not used by the
	// actual decoding loop.
	total uint32

	// needed is the amount of bytes missing. It should only be
	// incremented or decremented, never assigned. This ensures that more
	// than one message can be read into the buffer before the decoder is
	// ready to read them. If needed is zero, it means that all the
	// requested data have been read. If it is negative, then more data
	// then the request has been read. The decoding loop continues until
	// needed is > 0.
	needed int

	// size is the decoded message body size, not including message
	// header. It is stored in order to increment the ptr correctly after
	// reading a message.
	size uint32

	// ptr is the start index at the buffer at the current time. It is
	// incremented as we read through the buffer, and reset when we clean
	// the buffer.
	ptr uint32

	// m is the current decoded message. It is nil when we have not yet
	// decoded a header, and set to an zero-initialized message struct
	// when we have received the header. Comparing it to nil is used to
	// check what state the decoder is in (header decoding vs. body
	// decoding).
	m Message

	// buffer is the reading buffer.
	buffer []byte
}

// Reset resets the decoding state machine and reallocates the buffer to the
// current MessageSize. Reset will return an error if the buffer isn't empty,
// which may be the case if Greedy decoding has already been used.
func (d *Decoder) Reset() error {
	if d.total > 0 {
		return errors.New("buffer is not empty")
	}
	d.total = 0
	d.size = 0
	d.ptr = 0
	d.m = nil
	d.buffer = make([]byte, d.MessageSize)
	d.needed = HeaderSize
	return nil
}

// simpleNext is an inefficient but safe and stateless decoding mechanism.
func (d *Decoder) simpleNext() (Message, error) {
	b := make([]byte, 5)
	_, err := io.ReadFull(d.Reader, b)
	if err != nil {
		return nil, err
	}

	s := binary.LittleEndian.Uint32(b[0:4]) - HeaderSize
	mt := MessageType(b[4])
	m, err := d.Protocol.Message(mt)
	if err != nil {
		return nil, err
	}

	b = make([]byte, s)
	_, err = io.ReadFull(d.Reader, b)
	if err != nil {
		return nil, err
	}

	err = m.UnmarshalBinary(b)
	return m, err
}

// greedyNext is complicated and unsafe (parameters cannot be changed). The
// upside is that it can save a considerable amount of syscalls.
func (d *Decoder) greedyNext() (Message, error) {
	if d.buffer == nil {
		// Let's initialize.
		d.Reset()
	}

	var (
		err, readerr    error
		n, limit, total int
	)
	for {
		// Handle the data we got.
		for d.needed <= 0 {
			if d.m == nil { // Read a header if no message has been prepared.
				s := binary.LittleEndian.Uint32(d.buffer[d.ptr : d.ptr+4])
				if s > uint32(len(d.buffer)) {
					return nil, ErrMessageTooBig
				}

				d.size = s - HeaderSize
				mt := MessageType(d.buffer[d.ptr+4])

				// Update message body size, missing bytes and the current ptr.
				d.needed += int(d.size)
				d.ptr += HeaderSize

				// We try to fetch the message struct immediately - better to fail
				// early rather than late.
				if d.m, err = d.Protocol.Message(mt); err != nil {
					return nil, err
				}

			} else { // Otherwise, read a body for the message.
				if err = d.m.UnmarshalBinary(d.buffer[d.ptr : d.ptr+d.size]); err != nil {
					return nil, err
				}

				d.needed += HeaderSize
				d.ptr += d.size
				d.size = 0

				m := d.m
				d.m = nil
				return m, nil
			}
		}

		// Let's see if any readerr was present from last iteration...
		if readerr != nil {
			return nil, readerr
		}

		// Buffer cleanup.
		limit = len(d.buffer)
		total = int(d.total)
		if d.needed > limit-total {
			// The remaining part of the buffer is smaller than what we need,
			// so time for a cleaning. We could do it unconditionally for
			// every message, but a lot of small messages can usually fit in
			// the buffer, so why bother?
			copy(d.buffer, d.buffer[d.ptr:d.total])
			d.total -= d.ptr
			total = int(d.total)
			d.ptr = 0
		}

		// We need more data!
		n, readerr = d.Reader.Read(d.buffer[d.total:limit])
		d.total += uint32(n)
		d.needed -= n
	}
}

// NextMessage executes the decoder loop, returning the next message. It will
// continue reading from the configured reader until a message is found or an
// error occurs. NextMessage calls Reset if the internal buffer is nil for
// initialization.
func (d *Decoder) NextMessage() (Message, error) {
	if d.Greedy {
		return d.greedyNext()
	}
	return d.simpleNext()
}
<commit_msg>Just call Write, short write on io.Writer is an error<commit_after>package qp

import (
	"encoding"
	"encoding/binary"
	"errors"
	"io"
	"sync"
)

var (
	// ErrPayloadTooShort indicates that the message was not complete.
	ErrPayloadTooShort = errors.New("payload too short")

	// ErrMessageTooBig indicates that the message, when encoded and wrapped in
	// container, does not fit in the configured message size.
	ErrMessageTooBig = errors.New("message size larger than buffer")
)

// Protocol defines a protocol message encoder/decoder
type Protocol interface {
	MessageType(Message) (MessageType, error)
	Message(MessageType) (Message, error)
}

// Default is the protocol used by the raw Encode and Decode functions.
var Default = NineP2000

// MessageType is the type of the contained message.
type MessageType byte

// Message is an interface describing an item that can encode itself to a
// writer, decode itself from a reader. It is also capable of getting the
// message tag, which is merely a convenience feature to save a type assert
// for access to the tag.
type Message interface {
	encoding.BinaryUnmarshaler
	encoding.BinaryMarshaler
	GetTag() Tag
}

// Encoder handles writes encoded messages to an io.Writer.
type Encoder struct {
	// Protocol is the protocol codec used for encoding messages.
	Protocol Protocol

	// Writer is the writer to encode messages to.
	Writer io.Writer

	// MessageSize is the maximum message size negotiated for the protocol. It
	// is used to enforce a limit on writes.
	MessageSize uint32

	// writeLock is used to synchronize writes. Without it, messages would end
	// up interleaved and incomprehensible.
	writeLock sync.Mutex
}

// WriteMessage encodes a message and writes it to the Encoders associated
// io.Writer.
func (e *Encoder) WriteMessage(m Message) error {
	var (
		mt             MessageType
		msgbuf, header []byte
		err            error
	)

	if mt, err = e.Protocol.MessageType(m); err != nil {
		return err
	}

	if msgbuf, err = m.MarshalBinary(); err != nil {
		return err
	}

	if len(msgbuf)+HeaderSize > int(e.MessageSize) {
		return ErrMessageTooBig
	}

	header = make([]byte, HeaderSize)
	binary.LittleEndian.PutUint32(header[0:4], uint32(len(msgbuf)+HeaderSize))
	header[4] = byte(mt)

	e.writeLock.Lock()
	defer e.writeLock.Unlock()

	if _, err = e.Writer.Write(header); err != nil {
		return err
	}

	if _, err = e.Writer.Write(msgbuf); err != nil {
		return err
	}

	return nil
}

// Decoder reads messages from an io.Reader, calling a callback for each of them.
// message. Unlike Codec.Decode,
type Decoder struct {
	// Protocol is the protocol codec used for decoding messages.
	Protocol Protocol

	// Reader is the reader to decode from.
	Reader io.Reader

	// Greedy enables greedy decoding, which is whether or not the decoder
	// should try to read more than just the next message into the buffer.
	// This can save significant amount of Read calls, but must not be set if
	// the user intents to change the reader soon, as it may result in losing
	// a partial read. A common thing to do would be to enable Greedy after
	// protocol negotiation.
	Greedy bool

	// MessageSize is the maximum message size negotiated for the protocol. It
	// is used to allocate the decoding buffer.
	MessageSize uint32

	// total is the count of bytes in the buffer. It is used to keep track
	// of buffer usage (read offset and cleanup), and is not used by the
	// actual decoding loop.
	total uint32

	// needed is the amount of bytes missing. It should only be
	// incremented or decremented, never assigned. This ensures that more
	// than one message can be read into the buffer before the decoder is
	// ready to read them. If needed is zero, it means that all the
	// requested data have been read. If it is negative, then more data
	// then the request has been read. The decoding loop continues until
	// needed is > 0.
	needed int

	// size is the decoded message body size, not including message
	// header. It is stored in order to increment the ptr correctly after
	// reading a message.
	size uint32

	// ptr is the start index at the buffer at the current time. It is
	// incremented as we read through the buffer, and reset when we clean
	// the buffer.
	ptr uint32

	// m is the current decoded message. It is nil when we have not yet
	// decoded a header, and set to an zero-initialized message struct
	// when we have received the header. Comparing it to nil is used to
	// check what state the decoder is in (header decoding vs. body
	// decoding).
	m Message

	// buffer is the reading buffer.
	buffer []byte
}

// Reset resets the decoding state machine and reallocates the buffer to the
// current MessageSize. Reset will return an error if the buffer isn't empty,
// which may be the case if Greedy decoding has already been used.
func (d *Decoder) Reset() error {
	if d.total > 0 {
		return errors.New("buffer is not empty")
	}
	d.total = 0
	d.size = 0
	d.ptr = 0
	d.m = nil
	d.buffer = make([]byte, d.MessageSize)
	d.needed = HeaderSize
	return nil
}

// simpleNext is an inefficient but safe and stateless decoding mechanism.
func (d *Decoder) simpleNext() (Message, error) {
	b := make([]byte, 5)
	_, err := io.ReadFull(d.Reader, b)
	if err != nil {
		return nil, err
	}

	s := binary.LittleEndian.Uint32(b[0:4]) - HeaderSize
	mt := MessageType(b[4])
	m, err := d.Protocol.Message(mt)
	if err != nil {
		return nil, err
	}

	b = make([]byte, s)
	_, err = io.ReadFull(d.Reader, b)
	if err != nil {
		return nil, err
	}

	err = m.UnmarshalBinary(b)
	return m, err
}

// greedyNext is complicated and unsafe (parameters cannot be changed). The
// upside is that it can save a considerable amount of syscalls.
func (d *Decoder) greedyNext() (Message, error) {
	if d.buffer == nil {
		// Let's initialize.
		d.Reset()
	}

	var (
		err, readerr    error
		n, limit, total int
	)
	for {
		// Handle the data we got.
		for d.needed <= 0 {
			if d.m == nil { // Read a header if no message has been prepared.
				s := binary.LittleEndian.Uint32(d.buffer[d.ptr : d.ptr+4])
				if s > uint32(len(d.buffer)) {
					return nil, ErrMessageTooBig
				}

				d.size = s - HeaderSize
				mt := MessageType(d.buffer[d.ptr+4])

				// Update message body size, missing bytes and the current ptr.
				d.needed += int(d.size)
				d.ptr += HeaderSize

				// We try to fetch the message struct immediately - better to fail
				// early rather than late.
				if d.m, err = d.Protocol.Message(mt); err != nil {
					return nil, err
				}

			} else { // Otherwise, read a body for the message.
				if err = d.m.UnmarshalBinary(d.buffer[d.ptr : d.ptr+d.size]); err != nil {
					return nil, err
				}

				d.needed += HeaderSize
				d.ptr += d.size
				d.size = 0

				m := d.m
				d.m = nil
				return m, nil
			}
		}

		// Let's see if any readerr was present from last iteration...
		if readerr != nil {
			return nil, readerr
		}

		// Buffer cleanup.
		limit = len(d.buffer)
		total = int(d.total)
		if d.needed > limit-total {
			// The remaining part of the buffer is smaller than what we need,
			// so time for a cleaning. We could do it unconditionally for
			// every message, but a lot of small messages can usually fit in
			// the buffer, so why bother?
			copy(d.buffer, d.buffer[d.ptr:d.total])
			d.total -= d.ptr
			total = int(d.total)
			d.ptr = 0
		}

		// We need more data!
		n, readerr = d.Reader.Read(d.buffer[d.total:limit])
		d.total += uint32(n)
		d.needed -= n
	}
}

// NextMessage executes the decoder loop, returning the next message. It will
// continue reading from the configured reader until a message is found or an
// error occurs. NextMessage calls Reset if the internal buffer is nil for
// initialization.
func (d *Decoder) NextMessage() (Message, error) {
	if d.Greedy {
		return d.greedyNext()
	}
	return d.simpleNext()
}
<|endoftext|>


<commit_before>package ffparser

import (
	"strconv"
)

func toInteger64(str string) int64 {
	value, err := strconv.ParseInt(str, 10, 64)

	if err != nil {
		panic(err)
	}

	return value
}

func toInteger(str string) int {
	value, err := strconv.Atoi(str)

	if err != nil {
		panic(err)
	}

	return value
}

func float64ToString(v float64) string {
	return strconv.FormatFloat(v, 'f', -1, 64)
}

func toFloat64(str string) float64 {
	value, err := strconv.ParseFloat(str, 64)

	if err != nil {
		panic(err)
	}

	return value
}
<commit_msg>Tratando converter para aceitar strings vazias<commit_after>package ffparser

import (
	"strconv"
	"strings"
)

func toInteger64(str string) int64 {
	if strings.TrimSpace(str) == "" {
		return int64(0)
	}

	value, err := strconv.ParseInt(str, 10, 64)

	if err != nil {
		panic(err)
	}

	return value
}

func toInteger(str string) int {
	if strings.TrimSpace(str) == "" {
		return 0
	}

	value, err := strconv.Atoi(str)

	if err != nil {
		panic(err)
	}

	return value
}

func float64ToString(v float64) string {
	return strconv.FormatFloat(v, 'f', -1, 64)
}

func toFloat64(str string) float64 {
	if strings.TrimSpace(str) == "" {
		return float64(0)
	}

	value, err := strconv.ParseFloat(str, 64)

	if err != nil {
		panic(err)
	}

	return value
}
<|endoftext|>


<commit_before>package cookie551

import "net/http"

type Cookie struct {
	w http.ResponseWriter
	r *http.Request
}

func New(w http.ResponseWriter, r *http.Request) *Cookie {
	cookie := Cookie{
		w: w,
		r: r,
	}

	return &cookie
}
<commit_msg>refs #3 Cookie を登録するメソッドを実装する<commit_after>package cookie551

import (
	"net/http"
	"time"
)

type Cookie struct {
	w http.ResponseWriter
	r *http.Request
}

func New(w http.ResponseWriter, r *http.Request) *Cookie {
	cookie := Cookie{
		w: w,
		r: r,
	}

	return &cookie
}

func (c *Cookie) Set(name, value string, second time.Duration) {

	cookie := http.Cookie{
		Name:  name,
		value: value,
		Raw:   value,
	}

	if second == 0 {
		cookie.MaxAge = 0
	} else {
		expire := time.Now().Add(second * time.Second)
		cookie.Expires = expire
	}

	http.SetCookie(c.w, &cookie)

}
<|endoftext|>


<commit_before>package core

import (
	"html/template"
	"net/http"
	"os"
	"path/filepath"
)

type TemplateMap map[string]*template.Template

type Controller struct {
	BaseTemplate *template.Template
	Templates    TemplateMap
}

var TemplatePath = os.ExpandEnv("$GOPATH/src/github.com/octoberxp/glaze/views/")

func NewController() (*Controller, error) {
	tmpl, err := template.ParseFiles(TemplatePath + "main/base.html")
	if err != nil {
		return nil, err
	}

	return &Controller{BaseTemplate: tmpl}, nil
}

func (controller *Controller) RenderPage(writer http.ResponseWriter, templateName string, data interface{}) {
	err := controller.Templates[templateName+".html"].Execute(writer, data)

	if err != nil {
		http.Error(writer, err.Error(), http.StatusInternalServerError)
	}
}

func (controller *Controller) RenderTemplate(writer http.ResponseWriter, templateName string, data interface{}) {
	err := controller.Templates[templateName+".html"].Execute(writer, data)

	if err != nil {
		http.Error(writer, err.Error(), http.StatusInternalServerError)
	}
}

func (controller *Controller) LoadTemplates(templatePath string) {
	files, err := filepath.Glob(templatePath)
	if err != nil {
		panic(err)
	}

	templates := make(map[string]*template.Template, len(files))
	for _, file := range files {
		thisTemplate, err := controller.BaseTemplate.Clone()
		thisTemplate, err = thisTemplate.ParseFiles(file)
		if err != nil {
			panic(err)
		}

		templates[filepath.Base(file)] = thisTemplate
	}

	controller.Templates = templates
}
<commit_msg>Fixing a path<commit_after>package core

import (
	"html/template"
	"net/http"
	"os"
	"path/filepath"
)

type TemplateMap map[string]*template.Template

type Controller struct {
	BaseTemplate *template.Template
	Templates    TemplateMap
}

var TemplatePath = os.ExpandEnv("./views/")

func NewController() (*Controller, error) {
	tmpl, err := template.ParseFiles(TemplatePath + "main/base.html")
	if err != nil {
		return nil, err
	}

	return &Controller{BaseTemplate: tmpl}, nil
}

func (controller *Controller) RenderPage(writer http.ResponseWriter, templateName string, data interface{}) {
	err := controller.Templates[templateName+".html"].Execute(writer, data)

	if err != nil {
		http.Error(writer, err.Error(), http.StatusInternalServerError)
	}
}

func (controller *Controller) RenderTemplate(writer http.ResponseWriter, templateName string, data interface{}) {
	err := controller.Templates[templateName+".html"].Execute(writer, data)

	if err != nil {
		http.Error(writer, err.Error(), http.StatusInternalServerError)
	}
}

func (controller *Controller) LoadTemplates(templatePath string) {
	files, err := filepath.Glob(templatePath)
	if err != nil {
		panic(err)
	}

	templates := make(map[string]*template.Template, len(files))
	for _, file := range files {
		thisTemplate, err := controller.BaseTemplate.Clone()
		thisTemplate, err = thisTemplate.ParseFiles(file)
		if err != nil {
			panic(err)
		}

		templates[filepath.Base(file)] = thisTemplate
	}

	controller.Templates = templates
}
<|endoftext|>


<commit_before>package core

import (
	"fmt"

	"github.com/akutz/gofig"

	"github.com/emccode/rexray/util"
)

func init() {
	initDrivers()

	gofig.SetGlobalConfigPath(util.EtcDirPath())
	gofig.SetUserConfigPath(fmt.Sprintf("%s/.rexray", util.HomeDir()))

	gofig.Register(globalRegistration())
	gofig.Register(driverRegistration())
}

func globalRegistration() *gofig.Registration {
	r := gofig.NewRegistration("Global")
	r.Yaml(`
rexray:
    host: tcp://:7979
    logLevel: warn
`)
	r.Key(gofig.String, "h", "tcp://:7979",
		"The REX-Ray host", "rexray.host")
	r.Key(gofig.String, "l", "warn",
		"The log level (error, warn, info, debug)", "rexray.logLevel")
	return r
}

func driverRegistration() *gofig.Registration {
	r := gofig.NewRegistration("Driver")
	r.Yaml(`
rexray:
    osDrivers:
    - linux
    storageDrivers:
    - libstorage
    volumeDrivers:
    - docker
`)
	r.Key(gofig.String, "", "linux",
		"The OS drivers to consider", "rexray.osDrivers")
	r.Key(gofig.String, "", "",
		"The storage drivers to consider", "rexray.storageDrivers")
	r.Key(gofig.String, "", "docker",
		"The volume drivers to consider", "rexray.volumeDrivers")
	return r
}
<commit_msg>Revert "Fix for not setting Gofig global/user dirs"<commit_after>package core

import (
	"github.com/akutz/gofig"
)

func init() {
	initDrivers()
	gofig.Register(globalRegistration())
	gofig.Register(driverRegistration())
}

func globalRegistration() *gofig.Registration {
	r := gofig.NewRegistration("Global")
	r.Yaml(`
rexray:
    host: tcp://:7979
    logLevel: warn
`)
	r.Key(gofig.String, "h", "tcp://:7979",
		"The REX-Ray host", "rexray.host")
	r.Key(gofig.String, "l", "warn",
		"The log level (error, warn, info, debug)", "rexray.logLevel")
	return r
}

func driverRegistration() *gofig.Registration {
	r := gofig.NewRegistration("Driver")
	r.Yaml(`
rexray:
    osDrivers:
    - linux
    storageDrivers:
    - libstorage
    volumeDrivers:
    - docker
`)
	r.Key(gofig.String, "", "linux",
		"The OS drivers to consider", "rexray.osDrivers")
	r.Key(gofig.String, "", "",
		"The storage drivers to consider", "rexray.storageDrivers")
	r.Key(gofig.String, "", "docker",
		"The volume drivers to consider", "rexray.volumeDrivers")
	return r
}
<|endoftext|>