<commit_before>package ircclient

import (
	"strconv"
	"fmt"
	"regexp"
)

type authPlugin struct {
	ic         *IRCClient
	confplugin *ConfigPlugin
}

func NewauthPlugin() *authPlugin {
	return &authPlugin{nil, nil}
}
func (a *authPlugin) Register(cl *IRCClient) {
	a.ic = cl
	options := a.ic.GetOptions("Auth")
	for _, mask := range options {
		if _, err := regexp.Compile(mask); err != nil {
			panic(err.String())
		}
	}
	a.ic.RegisterCommandHandler("mya", 0, 0, a)
	a.ic.RegisterCommandHandler("myaccess", 0, 0, a)
	a.ic.RegisterCommandHandler("addaccess", 0, 400, a)
}
func (a *authPlugin) String() string {
	return "auth"
}
func (a *authPlugin) ProcessLine(msg *IRCMessage) {
	// Empty
}
func (a *authPlugin) Unregister() {
	// Empty
}
func (a *authPlugin) Info() string {
	return "Access control manager"
}
func (a *authPlugin) ProcessCommand(cmd *IRCCommand) {
	switch cmd.Command {
	case "myaccess":
		fallthrough
	case "mya":
		level := a.GetAccessLevel(cmd.Source)
		slevel := fmt.Sprintf("%d", level)
		a.ic.Reply(cmd, "Your access level is: "+slevel)
	case "addaccess":
		level := a.GetAccessLevel(cmd.Source)
		newlevel, err := strconv.Atoi(cmd.Args[1])
		if err != nil {
			a.ic.Reply(cmd, "Error: "+err.String())
		}
		if level < newlevel || level < 400 {
			a.ic.Reply(cmd, "You are not authorized to do this")
			return
		}
		if _, err := regexp.Compile(cmd.Args[0]); err != nil {
			a.ic.Reply(cmd, "Error: Unable to compile regexp: "+err.String())
			return
		}
		//a.ic.SetIntOption("Auth", cmd.Args[0], newlevel)
		a.SetAccessLevel(cmd.Args[0], newlevel)
		a.ic.Reply(cmd, "Permissions granted")
	case "delaccess":
		if len(cmd.Args) != 1 {
			a.ic.Reply(cmd, "delaccess takes mask to delete as an argument")
			return
		}
		level := a.GetAccessLevel(cmd.Source)
		dlevel, ok := a.ic.GetIntOption("Auth", cmd.Args[0])
		if ok != nil {
			if dlevel >= level || level != 500 {
				a.ic.Reply(cmd, "Can't remove mask: Has higher privileges than you")
				return
			}
			//a.ic.RemoveOption("Auth", cmd.Args[0])
			a.DelAccessLevel(cmd.Args[0])
			a.ic.Reply(cmd, "Successfully removed mask")
		} else {
			a.ic.Reply(cmd, "Mask not found")
		}
	}
}

func (a *authPlugin) SetAccessLevel(host string, level int) {
	a.ic.SetIntOption("Auth", host, level)
}

func (a *authPlugin) DelAccessLevel(mask string) {
	a.ic.RemoveOption("Auth", mask)
}

func (a *authPlugin) GetAccessLevel(host string) int {
	options := a.ic.GetOptions("Auth")
	maxaccess := 0
	for _, mask := range options {
		if match, _ := regexp.MatchString(mask, host); match == true {
			newaccess, _ := a.ic.GetIntOption("Auth", mask)
			if newaccess > maxaccess {
				maxaccess = newaccess
			}
		}
	}
	return maxaccess
}
<commit_msg>ircclient/auth: add Usage<commit_after>package ircclient

import (
	"strconv"
	"fmt"
	"regexp"
)

type authPlugin struct {
	ic         *IRCClient
	confplugin *ConfigPlugin
}

func NewauthPlugin() *authPlugin {
	return &authPlugin{nil, nil}
}
func (a *authPlugin) Register(cl *IRCClient) {
	a.ic = cl
	options := a.ic.GetOptions("Auth")
	for _, mask := range options {
		if _, err := regexp.Compile(mask); err != nil {
			panic(err.String())
		}
	}
	a.ic.RegisterCommandHandler("mya", 0, 0, a)
	a.ic.RegisterCommandHandler("myaccess", 0, 0, a)
	a.ic.RegisterCommandHandler("addaccess", 0, 400, a)
}
func (a *authPlugin) String() string {
	return "auth"
}

func (a *authPlugin) Usage(cmd string) string {
	switch cmd {
	case "mya":
		fallthrough
	case "myaccess":
		return cmd + ": tells you what access-level (i.e. permissions) you have"
	case "addaccess":
		return "addaccess <hostmask> <level>: adds access-level <level> for hostmask <hostmask>"
	}
}

func (a *authPlugin) ProcessLine(msg *IRCMessage) {
	// Empty
}
func (a *authPlugin) Unregister() {
	// Empty
}
func (a *authPlugin) Info() string {
	return "Access control manager"
}
func (a *authPlugin) ProcessCommand(cmd *IRCCommand) {
	switch cmd.Command {
	case "myaccess":
		fallthrough
	case "mya":
		level := a.GetAccessLevel(cmd.Source)
		slevel := fmt.Sprintf("%d", level)
		a.ic.Reply(cmd, "Your access level is: "+slevel)
	case "addaccess":
		level := a.GetAccessLevel(cmd.Source)
		newlevel, err := strconv.Atoi(cmd.Args[1])
		if err != nil {
			a.ic.Reply(cmd, "Error: "+err.String())
		}
		if level < newlevel || level < 400 {
			a.ic.Reply(cmd, "You are not authorized to do this")
			return
		}
		if _, err := regexp.Compile(cmd.Args[0]); err != nil {
			a.ic.Reply(cmd, "Error: Unable to compile regexp: "+err.String())
			return
		}
		//a.ic.SetIntOption("Auth", cmd.Args[0], newlevel)
		a.SetAccessLevel(cmd.Args[0], newlevel)
		a.ic.Reply(cmd, "Permissions granted")
	case "delaccess":
		if len(cmd.Args) != 1 {
			a.ic.Reply(cmd, "delaccess takes mask to delete as an argument")
			return
		}
		level := a.GetAccessLevel(cmd.Source)
		dlevel, ok := a.ic.GetIntOption("Auth", cmd.Args[0])
		if ok != nil {
			if dlevel >= level || level != 500 {
				a.ic.Reply(cmd, "Can't remove mask: Has higher privileges than you")
				return
			}
			//a.ic.RemoveOption("Auth", cmd.Args[0])
			a.DelAccessLevel(cmd.Args[0])
			a.ic.Reply(cmd, "Successfully removed mask")
		} else {
			a.ic.Reply(cmd, "Mask not found")
		}
	}
}

func (a *authPlugin) SetAccessLevel(host string, level int) {
	a.ic.SetIntOption("Auth", host, level)
}

func (a *authPlugin) DelAccessLevel(mask string) {
	a.ic.RemoveOption("Auth", mask)
}

func (a *authPlugin) GetAccessLevel(host string) int {
	options := a.ic.GetOptions("Auth")
	maxaccess := 0
	for _, mask := range options {
		if match, _ := regexp.MatchString(mask, host); match == true {
			newaccess, _ := a.ic.GetIntOption("Auth", mask)
			if newaccess > maxaccess {
				maxaccess = newaccess
			}
		}
	}
	return maxaccess
}
<|endoftext|>


<commit_before>package installer

import (
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/tsuru/tsuru-client/tsuru/installer/defaultconfig"
	"github.com/tsuru/tsuru-client/tsuru/installer/dm"
)

func resolveConfig(baseConfig string, customConfigs map[string]string) (string, error) {
	if baseConfig == "" {
		baseConfig = defaultconfig.Compose
	} else {
		b, err := ioutil.ReadFile(baseConfig)
		if err != nil {
			return "", err
		}
		baseConfig = string(b)
	}
	for k, v := range customConfigs {
		if v != "" {
			baseConfig = strings.Replace(baseConfig, fmt.Sprintf("{{%s}}", k), v, -1)
		}
	}
	return baseConfig, nil
}

func composeDeploy(c ServiceCluster, installConfig *InstallOpts) error {
	manager := c.GetManager()
	configs := map[string]string{
		"CLUSTER_ADDR":         manager.Base.Address,
		"CLUSTER_PRIVATE_ADDR": dm.GetPrivateIP(manager),
		"TSURU_API_IMAGE":      installConfig.ComponentsConfig.TsuruAPIImage,
	}
	config, err := resolveConfig(installConfig.ComposeFile, configs)
	if err != nil {
		return err
	}
	err = dm.WriterRemoteData(manager.Host, "/etc/tsuru/compose.yml", []byte(config))
	if err != nil {
		return fmt.Errorf("failed to write remote file: %s", err)
	}
	fmt.Print("Deploying compose file in cluster manager...\n")
	output, err := manager.Host.RunSSHCommand("sudo docker deploy -c /etc/tsuru/compose.yml tsuru")
	if err != nil {
		return err
	}
	fmt.Print(output)
	return nil
}
<commit_msg>Replace docker deploy by docker stack deploy #compose_deploy<commit_after>package installer

import (
	"fmt"
	"io/ioutil"
	"strings"

	"github.com/tsuru/tsuru-client/tsuru/installer/defaultconfig"
	"github.com/tsuru/tsuru-client/tsuru/installer/dm"
)

func resolveConfig(baseConfig string, customConfigs map[string]string) (string, error) {
	if baseConfig == "" {
		baseConfig = defaultconfig.Compose
	} else {
		b, err := ioutil.ReadFile(baseConfig)
		if err != nil {
			return "", err
		}
		baseConfig = string(b)
	}
	for k, v := range customConfigs {
		if v != "" {
			baseConfig = strings.Replace(baseConfig, fmt.Sprintf("{{%s}}", k), v, -1)
		}
	}
	return baseConfig, nil
}

func composeDeploy(c ServiceCluster, installConfig *InstallOpts) error {
	manager := c.GetManager()
	configs := map[string]string{
		"CLUSTER_ADDR":         manager.Base.Address,
		"CLUSTER_PRIVATE_ADDR": dm.GetPrivateIP(manager),
		"TSURU_API_IMAGE":      installConfig.ComponentsConfig.TsuruAPIImage,
	}
	config, err := resolveConfig(installConfig.ComposeFile, configs)
	if err != nil {
		return err
	}
	err = dm.WriterRemoteData(manager.Host, "/etc/tsuru/compose.yml", []byte(config))
	if err != nil {
		return fmt.Errorf("failed to write remote file: %s", err)
	}
	fmt.Print("Deploying compose file in cluster manager...\n")
	output, err := manager.Host.RunSSHCommand("sudo docker stack deploy -c /etc/tsuru/compose.yml tsuru")
	if err != nil {
		return err
	}
	fmt.Print(output)
	return nil
}
<|endoftext|>


<commit_before>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package cmd

import (
	"fmt"

	"github.com/TheThingsNetwork/ttn/ttnctl/util"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// applicationsCmd represents the applications command
var applicationsCmd = &cobra.Command{
	Use:   "applications",
	Short: "Show applications",
	Long:  `ttnctl applications retrieves the applications of the logged on user.`,
	Run: func(cmd *cobra.Command, args []string) {
		server := viper.GetString("ttn-account-server")
		_, err := util.NewRequestWithAuth(server, "GET", fmt.Sprintf("%s/applications", server), nil)
		if err != nil {
			ctx.WithError(err).Fatal("Create request failed")
		}
	},
}

func init() {
	RootCmd.AddCommand(applicationsCmd)
}
<commit_msg>[ttnctl-applications] Show applications<commit_after>// Copyright © 2016 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.

package cmd

import (
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/TheThingsNetwork/ttn/ttnctl/util"
	"github.com/gosuri/uitable"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

type app struct {
	EUI   string `json:"eui"`
	Name  string `json:"name"`
	Owner string `json:"owner"`
}

// applicationsCmd represents the applications command
var applicationsCmd = &cobra.Command{
	Use:   "applications",
	Short: "Show applications",
	Long:  `ttnctl applications retrieves the applications of the logged on user.`,
	Run: func(cmd *cobra.Command, args []string) {
		server := viper.GetString("ttn-account-server")
		req, err := util.NewRequestWithAuth(server, "GET", fmt.Sprintf("%s/applications", server), nil)
		if err != nil {
			ctx.WithError(err).Fatal("Failed to created authenticated request")
		}

		client := &http.Client{}
		resp, err := client.Do(req)
		if err != nil {
			ctx.WithError(err).Fatal("Failed to get applications")
		}
		if resp.StatusCode != http.StatusOK {
			ctx.Fatalf("Failed to get applications: %s", resp.Status)
		}

		defer resp.Body.Close()
		decoder := json.NewDecoder(resp.Body)
		var apps []*app
		err = decoder.Decode(&apps)
		if err != nil {
			ctx.WithError(err).Fatal("Failed to read applications")
		}

		ctx.Infof("Found %d application(s)", len(apps))
		table := uitable.New()
		table.MaxColWidth = 70
		table.AddRow("EUI", "Name", "Owner")
		for _, app := range apps {
			table.AddRow(app.EUI, app.Name, app.Owner)
		}
		fmt.Println(table)
	},
}

func init() {
	RootCmd.AddCommand(applicationsCmd)
}
<|endoftext|>


<commit_before>package testfixtures

import (
	"database/sql"
	"fmt"
	"io/ioutil"
	"path"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v2"
)

type Context struct {
	db            *sql.DB
	helper        Helper
	fixturesFiles []*fixtureFile
}

type fixtureFile struct {
	path       string
	fileName   string
	content    []byte
	insertSQLs []insertSQL
}

type insertSQL struct {
	sql    string
	params []interface{}
}

var (
	// ErrWrongCastNotAMap is returned when a map is not a map[interface{}]interface{}
	ErrWrongCastNotAMap = fmt.Errorf("Could not cast record: not a map[interface{}]interface{}")

	// ErrFileIsNotSliceOrMap is returned the the fixture file is not a slice or map.
	ErrFileIsNotSliceOrMap = fmt.Errorf("The fixture file is not a slice or map")

	// ErrKeyIsNotString is returned when a record is not of type string
	ErrKeyIsNotString = fmt.Errorf("Record map key is not string")
)

func NewFolder(db *sql.DB, helper Helper, folderName string) (*Context, error) {
	fixtures, err := fixturesFromFolder(folderName)
	if err != nil {
		return nil, err
	}

	c := &Context{
		db:            db,
		helper:        helper,
		fixturesFiles: fixtures,
	}

	if err = c.helper.init(c.db); err != nil {
		return nil, err
	}

	if err := c.buildInsertSQLs(); err != nil {
		return nil, err
	}

	return c, nil
}

func NewFiles(db *sql.DB, helper Helper, fileNames ...string) (*Context, error) {
	fixtures, err := fixturesFromFiles(fileNames...)
	if err != nil {
		return nil, err
	}

	c := &Context{
		db:            db,
		helper:        helper,
		fixturesFiles: fixtures,
	}

	if err = c.helper.init(c.db); err != nil {
		return nil, err
	}

	if err := c.buildInsertSQLs(); err != nil {
		return nil, err
	}

	return c, nil
}

func (c *Context) Load() error {
	if !skipDatabaseNameCheck {
		if !dbnameRegexp.MatchString(c.helper.databaseName(c.db)) {
			return errNotTestDatabase
		}
	}

	err := c.helper.disableReferentialIntegrity(c.db, func(tx *sql.Tx) error {
		for _, file := range c.fixturesFiles {
			if err := file.delete(tx, c.helper); err != nil {
				return err
			}

			err := c.helper.whileInsertOnTable(tx, file.fileNameWithoutExtension(), func() error {
				for _, i := range file.insertSQLs {
					if _, err := tx.Exec(i.sql, i.params...); err != nil {
						return err
					}
				}
				return nil
			})
			if err != nil {
				return err
			}
		}
		return nil
	})
	return err
}

func (c *Context) buildInsertSQLs() error {
	for _, f := range c.fixturesFiles {
		var records interface{}
		if err := yaml.Unmarshal(f.content, &records); err != nil {
			return err
		}

		switch records := records.(type) {
		case []interface{}:
			for _, record := range records {
				recordMap, ok := record.(map[interface{}]interface{})
				if !ok {
					return ErrWrongCastNotAMap
				}

				sql, values, err := f.buildInsertSQL(c.helper, recordMap)
				if err != nil {
					return err
				}

				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
			}
		case map[interface{}]interface{}:
			for _, record := range records {
				recordMap, ok := record.(map[interface{}]interface{})
				if !ok {
					return ErrWrongCastNotAMap
				}

				sql, values, err := f.buildInsertSQL(c.helper, recordMap)
				if err != nil {
					return err
				}

				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
			}
		default:
			return ErrFileIsNotSliceOrMap
		}
	}

	return nil
}

func (f *fixtureFile) fileNameWithoutExtension() string {
	return strings.Replace(f.fileName, filepath.Ext(f.fileName), "", 1)
}

func (f *fixtureFile) delete(tx *sql.Tx, h Helper) error {
	_, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", h.quoteKeyword(f.fileNameWithoutExtension())))
	return err
}

func (f *fixtureFile) buildInsertSQL(h Helper, record map[interface{}]interface{}) (sqlStr string, values []interface{}, err error) {
	var (
		sqlColumns []string
		sqlValues  []string
		i          = 1
	)
	for key, value := range record {
		keyStr, ok := key.(string)
		if !ok {
			err = ErrKeyIsNotString
			return
		}

		sqlColumns = append(sqlColumns, h.quoteKeyword(keyStr))

		switch h.paramType() {
		case paramTypeDollar:
			sqlValues = append(sqlValues, fmt.Sprintf("$%d", i))
		case paramTypeQuestion:
			sqlValues = append(sqlValues, "?")
		case paramTypeColon:
			switch {
			case isDateTime(value):
				sqlValues = append(sqlValues, fmt.Sprintf("to_date(:%d, 'YYYY-MM-DD HH24:MI:SS')", i))
			case isDate(value):
				sqlValues = append(sqlValues, fmt.Sprintf("to_date(:%d, 'YYYY-MM-DD')", i))
			case isTime(value):
				sqlValues = append(sqlValues, fmt.Sprintf("to_date(:%d, 'HH24:MI:SS')", i))
			default:
				sqlValues = append(sqlValues, fmt.Sprintf(":%d", i))
			}
		}
		i++
		values = append(values, value)
	}

	sqlStr = fmt.Sprintf(
		"INSERT INTO %s (%s) VALUES (%s)",
		h.quoteKeyword(f.fileNameWithoutExtension()),
		strings.Join(sqlColumns, ", "),
		strings.Join(sqlValues, ", "),
	)
	return
}

func fixturesFromFolder(folderName string) ([]*fixtureFile, error) {
	var files []*fixtureFile
	fileinfos, err := ioutil.ReadDir(folderName)
	if err != nil {
		return nil, err
	}

	for _, fileinfo := range fileinfos {
		if !fileinfo.IsDir() && filepath.Ext(fileinfo.Name()) == ".yml" {
			fixture := &fixtureFile{
				path:     path.Join(folderName, fileinfo.Name()),
				fileName: fileinfo.Name(),
			}
			fixture.content, err = ioutil.ReadFile(fixture.path)
			if err != nil {
				return nil, err
			}
			files = append(files, fixture)
		}
	}
	return files, nil
}

func fixturesFromFiles(fileNames ...string) ([]*fixtureFile, error) {
	var (
		fixtureFiles []*fixtureFile
		err          error
	)

	for _, f := range fileNames {
		fixture := &fixtureFile{
			path:     f,
			fileName: filepath.Base(f),
		}
		fixture.content, err = ioutil.ReadFile(fixture.path)
		if err != nil {
			return nil, err
		}
		fixtureFiles = append(fixtureFiles, fixture)
	}

	return fixtureFiles, nil
}
<commit_msg>Reducing duplication<commit_after>package testfixtures

import (
	"database/sql"
	"fmt"
	"io/ioutil"
	"path"
	"path/filepath"
	"strings"

	"gopkg.in/yaml.v2"
)

type Context struct {
	db            *sql.DB
	helper        Helper
	fixturesFiles []*fixtureFile
}

type fixtureFile struct {
	path       string
	fileName   string
	content    []byte
	insertSQLs []insertSQL
}

type insertSQL struct {
	sql    string
	params []interface{}
}

var (
	// ErrWrongCastNotAMap is returned when a map is not a map[interface{}]interface{}
	ErrWrongCastNotAMap = fmt.Errorf("Could not cast record: not a map[interface{}]interface{}")

	// ErrFileIsNotSliceOrMap is returned the the fixture file is not a slice or map.
	ErrFileIsNotSliceOrMap = fmt.Errorf("The fixture file is not a slice or map")

	// ErrKeyIsNotString is returned when a record is not of type string
	ErrKeyIsNotString = fmt.Errorf("Record map key is not string")
)

func NewFolder(db *sql.DB, helper Helper, folderName string) (*Context, error) {
	fixtures, err := fixturesFromFolder(folderName)
	if err != nil {
		return nil, err
	}

	c, err := newContext(db, helper, fixtures)
	if err != nil {
		return nil, err
	}

	return c, nil
}

func NewFiles(db *sql.DB, helper Helper, fileNames ...string) (*Context, error) {
	fixtures, err := fixturesFromFiles(fileNames...)
	if err != nil {
		return nil, err
	}

	c, err := newContext(db, helper, fixtures)
	if err != nil {
		return nil, err
	}

	return c, nil
}

func newContext(db *sql.DB, helper Helper, fixtures []*fixtureFile) (*Context, error) {
	c := &Context{
		db:            db,
		helper:        helper,
		fixturesFiles: fixtures,
	}

	if err := c.helper.init(c.db); err != nil {
		return nil, err
	}

	if err := c.buildInsertSQLs(); err != nil {
		return nil, err
	}

	return c, nil
}

func (c *Context) Load() error {
	if !skipDatabaseNameCheck {
		if !dbnameRegexp.MatchString(c.helper.databaseName(c.db)) {
			return errNotTestDatabase
		}
	}

	err := c.helper.disableReferentialIntegrity(c.db, func(tx *sql.Tx) error {
		for _, file := range c.fixturesFiles {
			if err := file.delete(tx, c.helper); err != nil {
				return err
			}

			err := c.helper.whileInsertOnTable(tx, file.fileNameWithoutExtension(), func() error {
				for _, i := range file.insertSQLs {
					if _, err := tx.Exec(i.sql, i.params...); err != nil {
						return err
					}
				}
				return nil
			})
			if err != nil {
				return err
			}
		}
		return nil
	})
	return err
}

func (c *Context) buildInsertSQLs() error {
	for _, f := range c.fixturesFiles {
		var records interface{}
		if err := yaml.Unmarshal(f.content, &records); err != nil {
			return err
		}

		switch records := records.(type) {
		case []interface{}:
			for _, record := range records {
				recordMap, ok := record.(map[interface{}]interface{})
				if !ok {
					return ErrWrongCastNotAMap
				}

				sql, values, err := f.buildInsertSQL(c.helper, recordMap)
				if err != nil {
					return err
				}

				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
			}
		case map[interface{}]interface{}:
			for _, record := range records {
				recordMap, ok := record.(map[interface{}]interface{})
				if !ok {
					return ErrWrongCastNotAMap
				}

				sql, values, err := f.buildInsertSQL(c.helper, recordMap)
				if err != nil {
					return err
				}

				f.insertSQLs = append(f.insertSQLs, insertSQL{sql, values})
			}
		default:
			return ErrFileIsNotSliceOrMap
		}
	}

	return nil
}

func (f *fixtureFile) fileNameWithoutExtension() string {
	return strings.Replace(f.fileName, filepath.Ext(f.fileName), "", 1)
}

func (f *fixtureFile) delete(tx *sql.Tx, h Helper) error {
	_, err := tx.Exec(fmt.Sprintf("DELETE FROM %s", h.quoteKeyword(f.fileNameWithoutExtension())))
	return err
}

func (f *fixtureFile) buildInsertSQL(h Helper, record map[interface{}]interface{}) (sqlStr string, values []interface{}, err error) {
	var (
		sqlColumns []string
		sqlValues  []string
		i          = 1
	)
	for key, value := range record {
		keyStr, ok := key.(string)
		if !ok {
			err = ErrKeyIsNotString
			return
		}

		sqlColumns = append(sqlColumns, h.quoteKeyword(keyStr))

		switch h.paramType() {
		case paramTypeDollar:
			sqlValues = append(sqlValues, fmt.Sprintf("$%d", i))
		case paramTypeQuestion:
			sqlValues = append(sqlValues, "?")
		case paramTypeColon:
			switch {
			case isDateTime(value):
				sqlValues = append(sqlValues, fmt.Sprintf("to_date(:%d, 'YYYY-MM-DD HH24:MI:SS')", i))
			case isDate(value):
				sqlValues = append(sqlValues, fmt.Sprintf("to_date(:%d, 'YYYY-MM-DD')", i))
			case isTime(value):
				sqlValues = append(sqlValues, fmt.Sprintf("to_date(:%d, 'HH24:MI:SS')", i))
			default:
				sqlValues = append(sqlValues, fmt.Sprintf(":%d", i))
			}
		}
		i++
		values = append(values, value)
	}

	sqlStr = fmt.Sprintf(
		"INSERT INTO %s (%s) VALUES (%s)",
		h.quoteKeyword(f.fileNameWithoutExtension()),
		strings.Join(sqlColumns, ", "),
		strings.Join(sqlValues, ", "),
	)
	return
}

func fixturesFromFolder(folderName string) ([]*fixtureFile, error) {
	var files []*fixtureFile
	fileinfos, err := ioutil.ReadDir(folderName)
	if err != nil {
		return nil, err
	}

	for _, fileinfo := range fileinfos {
		if !fileinfo.IsDir() && filepath.Ext(fileinfo.Name()) == ".yml" {
			fixture := &fixtureFile{
				path:     path.Join(folderName, fileinfo.Name()),
				fileName: fileinfo.Name(),
			}
			fixture.content, err = ioutil.ReadFile(fixture.path)
			if err != nil {
				return nil, err
			}
			files = append(files, fixture)
		}
	}
	return files, nil
}

func fixturesFromFiles(fileNames ...string) ([]*fixtureFile, error) {
	var (
		fixtureFiles []*fixtureFile
		err          error
	)

	for _, f := range fileNames {
		fixture := &fixtureFile{
			path:     f,
			fileName: filepath.Base(f),
		}
		fixture.content, err = ioutil.ReadFile(fixture.path)
		if err != nil {
			return nil, err
		}
		fixtureFiles = append(fixtureFiles, fixture)
	}

	return fixtureFiles, nil
}
<|endoftext|>


<commit_before>package otto

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/hashicorp/otto/app"
	"github.com/hashicorp/otto/appfile"
	"github.com/hashicorp/otto/directory"
	"github.com/hashicorp/otto/infrastructure"
	"github.com/hashicorp/otto/ui"
)

// Core is the main struct to use to interact with Otto as a library.
type Core struct {
	appfile   *appfile.File
	apps      map[app.Tuple]app.Factory
	dir       directory.Backend
	infras    map[string]infrastructure.Factory
	outputDir string
	ui        ui.Ui
}

// CoreConfig is configuration for creating a new core with NewCore.
type CoreConfig struct {
	// OutputDir is the directory where data will be written. Each
	// compilation will clear this directory prior to writing to it.
	OutputDir string

	// Appfile is the appfile that this core will be using for configuration.
	Appfile *appfile.File

	// Directory is the directory where data is stored about this Appfile.
	Directory directory.Backend

	// Apps is the map of available app implementations.
	Apps map[app.Tuple]app.Factory

	// Infrastructures is the map of available infrastructures. The
	// value is a factory that can create the infrastructure impl.
	Infrastructures map[string]infrastructure.Factory

	// Ui is the Ui that will be used to comunicate with the user.
	Ui ui.Ui
}

// NewCore creates a new core.
//
// Once this function is called, this CoreConfig should not be used again
// or modified, since the Core may use parts of it without deep copying.
func NewCore(c *CoreConfig) (*Core, error) {
	return &Core{
		appfile:   c.Appfile,
		apps:      c.Apps,
		dir:       c.Directory,
		infras:    c.Infrastructures,
		outputDir: c.OutputDir,
		ui:        c.Ui,
	}, nil
}

// Compile takes the Appfile and compiles all the resulting data.
func (c *Core) Compile() error {
	// Get the infra implementation for this
	infra, infraCtx, err := c.infra()
	if err != nil {
		return err
	}

	// Get the application implementation for this
	app, appCtx, err := c.app()
	if err != nil {
		return err
	}

	// Delete the prior output directory
	log.Printf("[INFO] deleting prior compilation contents: %s", c.outputDir)
	if err := os.RemoveAll(c.outputDir); err != nil {
		return err
	}

	// Compile!
	if _, err := infra.Compile(infraCtx); err != nil {
		return err
	}
	if _, err := app.Compile(appCtx); err != nil {
		return err
	}

	return nil
}

// Execute executes the given task for this Appfile.
func (c *Core) Execute(opts *ExecuteOpts) error {
	switch opts.Task {
	case ExecuteTaskDev:
		return c.executeApp(opts)
	case ExecuteTaskInfra:
		return c.executeInfra(opts)
	default:
		return fmt.Errorf("unknown task: %s", opts.Task)
	}
}

func (c *Core) executeApp(opts *ExecuteOpts) error {
	// Get the infra implementation for this
	app, appCtx, err := c.app()
	if err != nil {
		return err
	}

	// Set the action and action args
	appCtx.Action = opts.Action
	appCtx.ActionArgs = opts.Args

	// Build the infrastructure compilation context
	switch opts.Task {
	case ExecuteTaskDev:
		return app.Dev(appCtx)
	default:
		panic(fmt.Sprintf("uknown task: %s", opts.Task))
	}
}

func (c *Core) executeInfra(opts *ExecuteOpts) error {
	// Get the infra implementation for this
	infra, infraCtx, err := c.infra()
	if err != nil {
		return err
	}

	// Set the action and action args
	infraCtx.Action = opts.Action
	infraCtx.ActionArgs = opts.Args

	// Build the infrastructure compilation context
	return infra.Execute(infraCtx)
}

func (c *Core) app() (app.App, *app.Context, error) {
	// We need the configuration for the active infrastructure
	// so that we can build the tuple below
	config := c.appfile.ActiveInfrastructure()
	if config == nil {
		return nil, nil, fmt.Errorf(
			"infrastructure not found in appfile: %s",
			c.appfile.Project.Infrastructure)
	}

	// The tuple we're looking for is the application type, the
	// infrastructure type, and the infrastructure flavor. Build that
	// tuple.
	tuple := app.Tuple{
		App:         c.appfile.Application.Type,
		Infra:       c.appfile.Project.Infrastructure,
		InfraFlavor: config.Flavor,
	}

	// Look for the app impl. factory
	f, ok := c.apps[tuple]
	if !ok {
		return nil, nil, fmt.Errorf(
			"app implementation for tuple not found: %s", tuple)
	}

	// Start the impl.
	result, err := f()
	if err != nil {
		return nil, nil, fmt.Errorf(
			"app failed to start properly: %s", err)
	}

	// The output directory for data
	outputDir := filepath.Join(c.outputDir, "app")

	return result, &app.Context{
		Dir:         outputDir,
		Tuple:       tuple,
		Appfile:     c.appfile,
		Application: c.appfile.Application,
		Ui:          c.ui,
	}, nil
}

func (c *Core) infra() (infrastructure.Infrastructure, *infrastructure.Context, error) {
	// Get the infrastructure factory
	f, ok := c.infras[c.appfile.Project.Infrastructure]
	if !ok {
		return nil, nil, fmt.Errorf(
			"infrastructure type not supported: %s",
			c.appfile.Project.Infrastructure)
	}

	// Get the infrastructure configuration
	config := c.appfile.ActiveInfrastructure()
	if config == nil {
		return nil, nil, fmt.Errorf(
			"infrastructure not found in appfile: %s",
			c.appfile.Project.Infrastructure)
	}

	// Start the infrastructure implementation
	infra, err := f()
	if err != nil {
		return nil, nil, err
	}

	// The output directory for data
	outputDir := filepath.Join(
		c.outputDir, fmt.Sprintf("infra-%s", c.appfile.Project.Infrastructure))

	// Build the context
	return infra, &infrastructure.Context{
		Dir:       outputDir,
		Infra:     config,
		Ui:        c.ui,
		Directory: c.dir,
	}, nil
}
<commit_msg>otto: more logging<commit_after>package otto

import (
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/hashicorp/otto/app"
	"github.com/hashicorp/otto/appfile"
	"github.com/hashicorp/otto/directory"
	"github.com/hashicorp/otto/infrastructure"
	"github.com/hashicorp/otto/ui"
)

// Core is the main struct to use to interact with Otto as a library.
type Core struct {
	appfile   *appfile.File
	apps      map[app.Tuple]app.Factory
	dir       directory.Backend
	infras    map[string]infrastructure.Factory
	outputDir string
	ui        ui.Ui
}

// CoreConfig is configuration for creating a new core with NewCore.
type CoreConfig struct {
	// OutputDir is the directory where data will be written. Each
	// compilation will clear this directory prior to writing to it.
	OutputDir string

	// Appfile is the appfile that this core will be using for configuration.
	Appfile *appfile.File

	// Directory is the directory where data is stored about this Appfile.
	Directory directory.Backend

	// Apps is the map of available app implementations.
	Apps map[app.Tuple]app.Factory

	// Infrastructures is the map of available infrastructures. The
	// value is a factory that can create the infrastructure impl.
	Infrastructures map[string]infrastructure.Factory

	// Ui is the Ui that will be used to comunicate with the user.
	Ui ui.Ui
}

// NewCore creates a new core.
//
// Once this function is called, this CoreConfig should not be used again
// or modified, since the Core may use parts of it without deep copying.
func NewCore(c *CoreConfig) (*Core, error) {
	return &Core{
		appfile:   c.Appfile,
		apps:      c.Apps,
		dir:       c.Directory,
		infras:    c.Infrastructures,
		outputDir: c.OutputDir,
		ui:        c.Ui,
	}, nil
}

// Compile takes the Appfile and compiles all the resulting data.
func (c *Core) Compile() error {
	// Get the infra implementation for this
	infra, infraCtx, err := c.infra()
	if err != nil {
		return err
	}

	// Get the application implementation for this
	app, appCtx, err := c.app()
	if err != nil {
		return err
	}

	// Delete the prior output directory
	log.Printf("[INFO] deleting prior compilation contents: %s", c.outputDir)
	if err := os.RemoveAll(c.outputDir); err != nil {
		return err
	}

	// Compile!
	log.Printf("[INFO] running infra compile...")
	if _, err := infra.Compile(infraCtx); err != nil {
		return err
	}
	log.Printf("[INFO] running app compile...")
	if _, err := app.Compile(appCtx); err != nil {
		return err
	}

	return nil
}

// Execute executes the given task for this Appfile.
func (c *Core) Execute(opts *ExecuteOpts) error {
	switch opts.Task {
	case ExecuteTaskDev:
		return c.executeApp(opts)
	case ExecuteTaskInfra:
		return c.executeInfra(opts)
	default:
		return fmt.Errorf("unknown task: %s", opts.Task)
	}
}

func (c *Core) executeApp(opts *ExecuteOpts) error {
	// Get the infra implementation for this
	app, appCtx, err := c.app()
	if err != nil {
		return err
	}

	// Set the action and action args
	appCtx.Action = opts.Action
	appCtx.ActionArgs = opts.Args

	// Build the infrastructure compilation context
	switch opts.Task {
	case ExecuteTaskDev:
		return app.Dev(appCtx)
	default:
		panic(fmt.Sprintf("uknown task: %s", opts.Task))
	}
}

func (c *Core) executeInfra(opts *ExecuteOpts) error {
	// Get the infra implementation for this
	infra, infraCtx, err := c.infra()
	if err != nil {
		return err
	}

	// Set the action and action args
	infraCtx.Action = opts.Action
	infraCtx.ActionArgs = opts.Args

	// Build the infrastructure compilation context
	return infra.Execute(infraCtx)
}

func (c *Core) app() (app.App, *app.Context, error) {
	// We need the configuration for the active infrastructure
	// so that we can build the tuple below
	config := c.appfile.ActiveInfrastructure()
	if config == nil {
		return nil, nil, fmt.Errorf(
			"infrastructure not found in appfile: %s",
			c.appfile.Project.Infrastructure)
	}

	// The tuple we're looking for is the application type, the
	// infrastructure type, and the infrastructure flavor. Build that
	// tuple.
	tuple := app.Tuple{
		App:         c.appfile.Application.Type,
		Infra:       c.appfile.Project.Infrastructure,
		InfraFlavor: config.Flavor,
	}

	// Look for the app impl. factory
	f, ok := c.apps[tuple]
	if !ok {
		return nil, nil, fmt.Errorf(
			"app implementation for tuple not found: %s", tuple)
	}

	// Start the impl.
	result, err := f()
	if err != nil {
		return nil, nil, fmt.Errorf(
			"app failed to start properly: %s", err)
	}

	// The output directory for data
	outputDir := filepath.Join(c.outputDir, "app")

	return result, &app.Context{
		Dir:         outputDir,
		Tuple:       tuple,
		Appfile:     c.appfile,
		Application: c.appfile.Application,
		Ui:          c.ui,
	}, nil
}

func (c *Core) infra() (infrastructure.Infrastructure, *infrastructure.Context, error) {
	// Get the infrastructure factory
	f, ok := c.infras[c.appfile.Project.Infrastructure]
	if !ok {
		return nil, nil, fmt.Errorf(
			"infrastructure type not supported: %s",
			c.appfile.Project.Infrastructure)
	}

	// Get the infrastructure configuration
	config := c.appfile.ActiveInfrastructure()
	if config == nil {
		return nil, nil, fmt.Errorf(
			"infrastructure not found in appfile: %s",
			c.appfile.Project.Infrastructure)
	}

	// Start the infrastructure implementation
	infra, err := f()
	if err != nil {
		return nil, nil, err
	}

	// The output directory for data
	outputDir := filepath.Join(
		c.outputDir, fmt.Sprintf("infra-%s", c.appfile.Project.Infrastructure))

	// Build the context
	return infra, &infrastructure.Context{
		Dir:       outputDir,
		Infra:     config,
		Ui:        c.ui,
		Directory: c.dir,
	}, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
)

// Tree represents a binary tree structure.
type Tree struct {
	Left  *Tree
	Value int
	Right *Tree
}

func stringSliceToIntSlice(sString []string) []int {
	var sInt = []int{}
	for _, s := range sString {
		i, err := strconv.Atoi(s)
		if err != nil {
			log.Fatal(err)
		}
		sInt = append(sInt, i)
	}
	return sInt
}

func getMatrixFromDataFile(filePath string) ([][]int, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var matrix = [][]int{}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		r := strings.Fields(scanner.Text())
		intSlice := stringSliceToIntSlice(r)
		matrix = append(matrix, intSlice)
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return matrix, nil
}

func displayMatrix(matrix [][]int) {
	for _, r := range matrix {
		fmt.Println(r)
	}
}

func main() {
	matrix, err := getMatrixFromDataFile("./smalldata")
	if err != nil {
		log.Fatal(err)
	}

	displayMatrix(matrix)

	// insert(matrix, 0, 0)

}
<commit_msg>create tree node<commit_after>package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
)

// Tree represents a binary tree structure.
type Tree struct {
	Left  *Tree
	Value int
	Right *Tree
}

func stringSliceToIntSlice(sString []string) []int {
	var sInt = []int{}
	for _, s := range sString {
		i, err := strconv.Atoi(s)
		if err != nil {
			log.Fatal(err)
		}
		sInt = append(sInt, i)
	}
	return sInt
}

func getMatrixFromDataFile(filePath string) ([][]int, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	var matrix = [][]int{}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		r := strings.Fields(scanner.Text())
		intSlice := stringSliceToIntSlice(r)
		matrix = append(matrix, intSlice)
	}

	if err := scanner.Err(); err != nil {
		return nil, err
	}

	return matrix, nil
}

func displayMatrix(matrix [][]int) {
	for _, r := range matrix {
		fmt.Println(r)
	}
}

func main() {
	matrix, err := getMatrixFromDataFile("./smalldata")
	if err != nil {
		log.Fatal(err)
	}

	displayMatrix(matrix)

	for i := 0; i < len(matrix); i++ {
		for j := 0; j < len(matrix[i]); j++ {
			if i+1 == len(matrix) {
				fmt.Println(matrix[i][j])
			} else {
				fmt.Println(matrix[i][j], matrix[i+1][j], matrix[i+1][j+1])
			}
		}
	}
}
<|endoftext|>


<commit_before>package kafka

import (
	"github.com/Shopify/sarama"
	"github.com/gotgo/fw/logging"
)

type Consumer struct {
	Name            string
	StartingOffsets map[int]int64
	Log             logging.Logger `inject:""`
	Topic           string
	stopper         chan struct{}
	events          chan *ConsumerEvent
	client          *sarama.Client
}

func NewConsumer(client *sarama.Client, name, topic string, startingOffsets map[int]int64) *Consumer {
	consumer := &Consumer{
		Name:            name,
		StartingOffsets: startingOffsets,
		Topic:           topic,
		events:          make(chan *ConsumerEvent),
		client:          client,
	}
	return consumer
}

// Run - Nonblocking
func (c *Consumer) Run() {
	consumers := c.setupConsumers()
	c.consume(consumers)
}

func (c *Consumer) Events() <-chan *ConsumerEvent {
	return c.events
}

func (c *Consumer) Shutdown() {
	if c.stopper != nil {
		close(c.stopper)
	}
}

func (c *Consumer) setupConsumers() []*sarama.Consumer {
	offsets := c.StartingOffsets
	count := len(offsets)
	consumers := make([]*sarama.Consumer, count)
	i := 0
	for partition, offset := range offsets {
		if consumer, err := c.getConsumer(c.client, c.Topic, int32(partition), c.Name, offset); err != nil {
			panic(err)
		} else {
			consumers[i] = consumer
		}
		i++
	}
	return consumers
}

func (c *Consumer) consume(consumers []*sarama.Consumer) {
	c.stopper = make(chan struct{})
	for _, consumer := range consumers {
		defer consumer.Close()
	}

	for _, consumer := range consumers {
		go func() {
			select {
			case value := <-consumer.Events():
				evt := &ConsumerEvent{
					Error:     value.Err,
					Message:   value.Value,
					Offset:    value.Offset,
					Partition: value.Partition,
				}
				c.events <- evt
			case <-c.stopper:
				return
			}
		}()
	}
}

func (c *Consumer) getConsumer(client *sarama.Client, topic string, partition int32, consumerName string, startAtOffset int64) (*sarama.Consumer, error) {
	config := sarama.NewConsumerConfig()
	config.EventBufferSize = 1
	config.OffsetMethod = sarama.OffsetMethodManual
	config.OffsetValue = startAtOffset
	consumer, err := sarama.NewConsumer(client, topic, partition, consumerName, config)
	if err != nil {
		return nil, err
	}
	return consumer, nil
}
<commit_msg>cleanup<commit_after>package kafka

import (
	"github.com/Shopify/sarama"
	"github.com/gotgo/fw/logging"
)

type Consumer struct {
	ClientName      string
	StartingOffsets map[int]int64
	Log             logging.Logger `inject:""`
	Topic           string
	stopper         chan struct{}
	events          chan *ConsumerEvent
	client          *sarama.Client
}

func NewConsumer(client *sarama.Client, clientName, topic string, startingOffsets map[int]int64) *Consumer {
	consumer := &Consumer{
		ClientName:      clientName,
		StartingOffsets: startingOffsets,
		Topic:           topic,
		events:          make(chan *ConsumerEvent),
		client:          client,
	}
	return consumer
}

// Run - Nonblocking
func (c *Consumer) Run() {
	consumers := c.setupConsumers()
	c.consume(consumers)
}

func (c *Consumer) Events() <-chan *ConsumerEvent {
	return c.events
}

func (c *Consumer) Shutdown() {
	if c.stopper != nil {
		close(c.stopper)
	}
}

func (c *Consumer) setupConsumers() []*sarama.Consumer {
	offsets := c.StartingOffsets
	count := len(offsets)
	consumers := make([]*sarama.Consumer, count)
	i := 0
	for partition, offset := range offsets {
		if consumer, err := c.getConsumer(c.client, c.Topic, int32(partition), c.ClientName, offset); err != nil {
			panic(err)
		} else {
			consumers[i] = consumer
		}
		i++
	}
	return consumers
}

func (c *Consumer) consume(consumers []*sarama.Consumer) {
	c.stopper = make(chan struct{})
	for _, consumer := range consumers {
		defer consumer.Close()
	}

	for _, consumer := range consumers {
		go func() {
			select {
			case value := <-consumer.Events():
				evt := &ConsumerEvent{
					Error:     value.Err,
					Message:   value.Value,
					Offset:    value.Offset,
					Partition: value.Partition,
				}
				c.events <- evt
			case <-c.stopper:
				return
			}
		}()
	}
}

func (c *Consumer) getConsumer(client *sarama.Client, topic string, partition int32, consumerName string, startAtOffset int64) (*sarama.Consumer, error) {
	config := sarama.NewConsumerConfig()
	config.EventBufferSize = 1
	config.OffsetMethod = sarama.OffsetMethodManual
	config.OffsetValue = startAtOffset
	consumer, err := sarama.NewConsumer(client, topic, partition, consumerName, config)
	if err != nil {
		return nil, err
	}
	return consumer, nil
}
<|endoftext|>


<commit_before>package gonx

import (
	. "github.com/smartystreets/goconvey/convey"
	"github.com/stretchr/testify/assert"
	"testing"
)

func TestEntry(t *testing.T) {
	Convey("Test get Entry fields", t, func() {
		entry := NewEntry(Fields{"foo": "1", "bar": "not a number"})

		Convey("Get raw string value", func() {
			// Get existings field
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "1")

			// Get field that does not exist
			val, err = entry.Field("baz")
			So(err, ShouldNotBeNil)
			So(val, ShouldEqual, "")
		})

		Convey("Get float values", func() {
			// Get existings field
			val, err := entry.FloatField("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, 1.0)

			// Type casting eror
			val, err = entry.FloatField("bar")
			So(err, ShouldNotBeNil)
			So(val, ShouldEqual, 0.0)

			// Get field that does not exist
			val, err = entry.FloatField("baz")
			So(err, ShouldNotBeNil)
			So(val, ShouldEqual, 0.0)
		})
	})

	Convey("Test set Entry fields", t, func() {
		entry := NewEmptyEntry()

		Convey("Set raw string value", func() {
			// Set field value
			entry.SetField("foo", "123")
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "123")

			// Ovewrite value
			entry.SetField("foo", "234")
			val, err = entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "234")
		})

		Convey("Test set float Entry fields", func() {
			entry.SetFloatField("foo", 123.4567)
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "123.46")
		})

		Convey("Test set uint Entry fields", func() {
			entry.SetUintField("foo", 123)
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "123")
		})
	})

	Convey("Test Entries merge", t, func() {
		entry1 := NewEntry(Fields{"foo": "1", "bar": "hello"})
		entry2 := NewEntry(Fields{"foo": "2", "bar": "hello", "name": "alpha"})
		entry1.Merge(entry2)

		val, err := entry1.Field("foo")
		So(err, ShouldBeNil)
		So(val, ShouldEqual, "2")

		val, err = entry1.Field("bar")
		So(err, ShouldBeNil)
		So(val, ShouldEqual, "hello")

		val, err = entry1.Field("name")
		So(err, ShouldBeNil)
		So(val, ShouldEqual, "alpha")
	})

	Convey("Test Entry fields hash", t, func() {
		entry1 := NewEntry(Fields{"foo": "1", "bar": "Hello world #1", "name": "alpha"})
		entry2 := NewEntry(Fields{"foo": "2", "bar": "Hello world #2", "name": "alpha"})
		entry3 := NewEntry(Fields{"foo": "2", "bar": "Hello world #3", "name": "alpha"})
		entry4 := NewEntry(Fields{"foo": "3", "bar": "Hello world #4", "name": "beta"})

		fields := []string{"name"}
		So(entry1.FieldsHash(fields), ShouldEqual, entry2.FieldsHash(fields))
		So(entry1.FieldsHash(fields), ShouldEqual, entry3.FieldsHash(fields))
		So(entry1.FieldsHash(fields), ShouldNotEqual, entry4.FieldsHash(fields))

		fields = []string{"name", "foo"}
		So(entry1.FieldsHash(fields), ShouldNotEqual, entry2.FieldsHash(fields))
		So(entry2.FieldsHash(fields), ShouldEqual, entry3.FieldsHash(fields))
		So(entry1.FieldsHash(fields), ShouldNotEqual, entry4.FieldsHash(fields))
		So(entry2.FieldsHash(fields), ShouldNotEqual, entry4.FieldsHash(fields))
	})

	Convey("Test partial Entry", t, func() {
		entry := NewEntry(Fields{"foo": "1", "bar": "Hello world #1", "name": "alpha"})
		partial := entry.Partial([]string{"name", "foo"})

		assert.Equal(t, len(partial.fields), 2)
		val, _ := partial.Field("name")
		So(val, ShouldEqual, "alpha")
		val, _ = partial.Field("foo")
		So(val, ShouldEqual, "1")
	})
}
<commit_msg>drop testify dependency for entry tests<commit_after>package gonx

import (
	. "github.com/smartystreets/goconvey/convey"
	"testing"
)

func TestEntry(t *testing.T) {
	Convey("Test get Entry fields", t, func() {
		entry := NewEntry(Fields{"foo": "1", "bar": "not a number"})

		Convey("Get raw string value", func() {
			// Get existings field
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "1")

			// Get field that does not exist
			val, err = entry.Field("baz")
			So(err, ShouldNotBeNil)
			So(val, ShouldEqual, "")
		})

		Convey("Get float values", func() {
			// Get existings field
			val, err := entry.FloatField("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, 1.0)

			// Type casting eror
			val, err = entry.FloatField("bar")
			So(err, ShouldNotBeNil)
			So(val, ShouldEqual, 0.0)

			// Get field that does not exist
			val, err = entry.FloatField("baz")
			So(err, ShouldNotBeNil)
			So(val, ShouldEqual, 0.0)
		})
	})

	Convey("Test set Entry fields", t, func() {
		entry := NewEmptyEntry()

		Convey("Set raw string value", func() {
			// Set field value
			entry.SetField("foo", "123")
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "123")

			// Ovewrite value
			entry.SetField("foo", "234")
			val, err = entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "234")
		})

		Convey("Test set float Entry fields", func() {
			entry.SetFloatField("foo", 123.4567)
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "123.46")
		})

		Convey("Test set uint Entry fields", func() {
			entry.SetUintField("foo", 123)
			val, err := entry.Field("foo")
			So(err, ShouldBeNil)
			So(val, ShouldEqual, "123")
		})
	})

	Convey("Test Entries merge", t, func() {
		entry1 := NewEntry(Fields{"foo": "1", "bar": "hello"})
		entry2 := NewEntry(Fields{"foo": "2", "bar": "hello", "name": "alpha"})
		entry1.Merge(entry2)

		val, err := entry1.Field("foo")
		So(err, ShouldBeNil)
		So(val, ShouldEqual, "2")

		val, err = entry1.Field("bar")
		So(err, ShouldBeNil)
		So(val, ShouldEqual, "hello")

		val, err = entry1.Field("name")
		So(err, ShouldBeNil)
		So(val, ShouldEqual, "alpha")
	})

	Convey("Test Entry fields hash", t, func() {
		entry1 := NewEntry(Fields{"foo": "1", "bar": "Hello world #1", "name": "alpha"})
		entry2 := NewEntry(Fields{"foo": "2", "bar": "Hello world #2", "name": "alpha"})
		entry3 := NewEntry(Fields{"foo": "2", "bar": "Hello world #3", "name": "alpha"})
		entry4 := NewEntry(Fields{"foo": "3", "bar": "Hello world #4", "name": "beta"})

		fields := []string{"name"}
		So(entry1.FieldsHash(fields), ShouldEqual, entry2.FieldsHash(fields))
		So(entry1.FieldsHash(fields), ShouldEqual, entry3.FieldsHash(fields))
		So(entry1.FieldsHash(fields), ShouldNotEqual, entry4.FieldsHash(fields))

		fields = []string{"name", "foo"}
		So(entry1.FieldsHash(fields), ShouldNotEqual, entry2.FieldsHash(fields))
		So(entry2.FieldsHash(fields), ShouldEqual, entry3.FieldsHash(fields))
		So(entry1.FieldsHash(fields), ShouldNotEqual, entry4.FieldsHash(fields))
		So(entry2.FieldsHash(fields), ShouldNotEqual, entry4.FieldsHash(fields))
	})

	Convey("Test partial Entry", t, func() {
		entry := NewEntry(Fields{"foo": "1", "bar": "Hello world #1", "name": "alpha"})
		partial := entry.Partial([]string{"name", "foo"})

		So(len(partial.fields), ShouldEqual, 2)
		val, _ := partial.Field("name")
		So(val, ShouldEqual, "alpha")
		val, _ = partial.Field("foo")
		So(val, ShouldEqual, "1")
	})
}
<|endoftext|>


<commit_before>package build

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"koding/kite/kd/util"
	"koding/kite/kd/util/deps"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"text/template"
)

type Build struct {
	AppName    string
	Version    string
	Output     string
	BinaryPath string
	ImportPath string
	Files      string

	// used for pkg packaging
	Identifier string
}

func NewBuild() *Build {
	return &Build{}
}

func (b *Build) Definition() string {
	return "Build deployable install packages"
}

func (b *Build) Exec(args []string) error {
	usage := "Usage: kd build --import <importPath> || --bin <binaryPath> --files <filesPath>"
	if len(args) == 0 {
		return errors.New(usage)
	}

	f := flag.NewFlagSet("build", flag.ContinueOnError)
	f.StringVar(&b.ImportPath, "import", "", "Go importpath to be packaged")
	f.StringVar(&b.BinaryPath, "bin", "", "Binary to be packaged")
	f.StringVar(&b.Files, "files", "", "Files to be included with the package")
	f.StringVar(&b.Identifier, "identifier", "com.koding", "Pkg identifier")
	f.Parse(args)

	if b.BinaryPath != "" {
		b.AppName = filepath.Base(b.BinaryPath)
	} else if b.ImportPath != "" {
		b.AppName = filepath.Base(b.ImportPath)
	} else {
		return errors.New("build: --import or --bin should be defined.")
	}

	b.Version = "0.0.1"
	b.Output = fmt.Sprintf("%s.%s-%s", b.AppName, runtime.GOOS, runtime.GOARCH)

	err := b.do()
	if err != nil {
		return err
	}

	return nil
}

func (b *Build) do() error {
	switch runtime.GOOS {
	case "darwin":
		err := b.darwin()
		if err != nil {
			log.Println("darwin:", err)
		}
	case "linux":
		err := b.linux()
		if err != nil {
			log.Println("linux:", err)
		}
	}

	// also create a tar.gz regardless of os
	return b.tarGzFile()
}

func (b *Build) linux() error {
	return nil
}

func (b *Build) tarGzFile() error {
	buildFolder, err := ioutil.TempDir(".", "kd-build")
	if err != nil {
		return err
	}
	defer os.RemoveAll(buildFolder)

	if b.ImportPath != "" {
		gopath := os.Getenv("GOPATH")
		if gopath == "" {
			return errors.New("GOPATH is not set")
		}

		// or use "go list <importPath>" for all packages and commands
		packages := []string{b.ImportPath}
		d, err := deps.LoadDeps(packages...)
		if err != nil {
			return err
		}

		err = d.InstallDeps()
		if err != nil {
			return err
		}

		buildFolder = filepath.Join(d.BuildGoPath, b.AppName)
	} else {
		err := util.Copy(b.BinaryPath, buildFolder)
		if err != nil {
			log.Println("copy assets", err)
		}
	}

	// include given files
	if b.Files != "" {
		files := strings.Split(b.Files, ",")
		for _, path := range files {
			err := util.Copy(path, buildFolder)
			if err != nil {
				log.Println("copy assets", err)
			}
		}
	}

	// create tar.gz file from final director
	tarFile := fmt.Sprintf("%s.%s-%s.tar.gz", b.AppName, runtime.GOOS, runtime.GOARCH)
	err = util.MakeTar(tarFile, buildFolder)
	if err != nil {
		return err
	}

	fmt.Printf("'%s' is created and ready for deploy\n", tarFile)
	return nil
}

// darwin is building a new .pkg installer for darwin based OS'es.
func (b *Build) darwin() error {
	version := b.Version
	if b.Output == "" {
		b.Output = fmt.Sprintf("kite-%s", b.AppName)
	}

	installRoot, err := ioutil.TempDir(".", "kd-build-darwin_")
	if err != nil {
		return err
	}
	// defer os.RemoveAll(installRoot)

	buildFolder, err := ioutil.TempDir(".", "kd-build-darwin_")
	if err != nil {
		return err
	}
	// defer os.RemoveAll(buildFolder)

	scriptDir := filepath.Join(buildFolder, "scripts")
	installRootUsr := filepath.Join(installRoot, "/usr/local/bin")

	os.MkdirAll(installRootUsr, 0755)
	err = util.Copy(b.BinaryPath, installRootUsr+"/"+b.AppName)
	if err != nil {
		return err
	}

	tempDest, err := ioutil.TempDir("", "tempDest")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tempDest)

	b.createScripts(scriptDir)
	b.createLaunchAgent(installRoot)

	cmdPkg := exec.Command("pkgbuild",
		"--identifier", fmt.Sprintf("%s.kite.%s.pkg", b.Identifier, b.AppName),
		"--version", version,
		"--scripts", scriptDir,
		"--root", installRoot,
		"--install-location", "/",
		fmt.Sprintf("%s/%s.kite.%s.pkg", tempDest, b.Identifier, b.AppName),
		// used for next step, also set up for distribution.xml
	)

	_, err = cmdPkg.CombinedOutput()
	if err != nil {
		return err
	}

	distributionFile := filepath.Join(buildFolder, "Distribution.xml")
	resources := filepath.Join(buildFolder, "Resources")

	targetFile := b.Output + ".pkg"

	b.createDistribution(distributionFile)

	cmdBuild := exec.Command("productbuild",
		"--distribution", distributionFile,
		"--resources", resources,
		"--package-path", tempDest,
		targetFile,
	)

	_, err = cmdBuild.CombinedOutput()
	if err != nil {
		return err
	}

	fmt.Printf("'%s' is created and ready for deploy\n", targetFile)
	return nil
}

func (b *Build) createLaunchAgent(rootDir string) {
	launchDir := fmt.Sprintf("%s/Library/LaunchAgents/", rootDir)
	os.MkdirAll(launchDir, 0700)

	launchFile := fmt.Sprintf("%s/%s.kite.%s.plist", launchDir, b.Identifier, b.AppName)

	lFile, err := os.Create(launchFile)
	if err != nil {
		log.Fatalln(err)
	}

	t := template.Must(template.New("launchAgent").Parse(launchAgent))
	t.Execute(lFile, b)

}

func (b *Build) createDistribution(file string) {
	distFile, err := os.Create(file)
	if err != nil {
		log.Fatalln(err)
	}

	t := template.Must(template.New("distribution").Parse(distribution))
	t.Execute(distFile, b)

}

func (b *Build) createScripts(scriptDir string) {
	os.MkdirAll(scriptDir, 0700) // does return nil if exists

	postInstallFile, err := os.Create(scriptDir + "/postInstall")
	if err != nil {
		log.Fatalln(err)
	}
	postInstallFile.Chmod(0755)

	preInstallFile, err := os.Create(scriptDir + "/preInstall")
	if err != nil {
		log.Fatalln(err)
	}
	preInstallFile.Chmod(0755)

	t := template.Must(template.New("postInstall").Parse(postInstall))
	t.Execute(postInstallFile, b)

	t = template.Must(template.New("preInstall").Parse(preInstall))
	t.Execute(preInstallFile, b)
}

func fileExist(dir string) bool {
	var err error
	_, err = os.Stat(dir)
	if err == nil {
		return true // file exist
	}

	if os.IsNotExist(err) {
		return false // file does not exist
	}

	panic(err) // permission errors or something else bad
}
<commit_msg>build: enable cleanup defers<commit_after>package build

import (
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"koding/kite/kd/util"
	"koding/kite/kd/util/deps"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"text/template"
)

type Build struct {
	AppName    string
	Version    string
	Output     string
	BinaryPath string
	ImportPath string
	Files      string

	// used for pkg packaging
	Identifier string
}

func NewBuild() *Build {
	return &Build{}
}

func (b *Build) Definition() string {
	return "Build deployable install packages"
}

func (b *Build) Exec(args []string) error {
	usage := "Usage: kd build --import <importPath> || --bin <binaryPath> --files <filesPath>"
	if len(args) == 0 {
		return errors.New(usage)
	}

	f := flag.NewFlagSet("build", flag.ContinueOnError)
	f.StringVar(&b.ImportPath, "import", "", "Go importpath to be packaged")
	f.StringVar(&b.BinaryPath, "bin", "", "Binary to be packaged")
	f.StringVar(&b.Files, "files", "", "Files to be included with the package")
	f.StringVar(&b.Identifier, "identifier", "com.koding", "Pkg identifier")
	f.Parse(args)

	if b.BinaryPath != "" {
		b.AppName = filepath.Base(b.BinaryPath)
	} else if b.ImportPath != "" {
		b.AppName = filepath.Base(b.ImportPath)
	} else {
		return errors.New("build: --import or --bin should be defined.")
	}

	b.Version = "0.0.1"
	b.Output = fmt.Sprintf("%s.%s-%s", b.AppName, runtime.GOOS, runtime.GOARCH)

	err := b.do()
	if err != nil {
		return err
	}

	return nil
}

func (b *Build) do() error {
	switch runtime.GOOS {
	case "darwin":
		err := b.darwin()
		if err != nil {
			log.Println("darwin:", err)
		}
	case "linux":
		err := b.linux()
		if err != nil {
			log.Println("linux:", err)
		}
	}

	// also create a tar.gz regardless of os
	return b.tarGzFile()
}

func (b *Build) linux() error {
	return nil
}

func (b *Build) tarGzFile() error {
	buildFolder, err := ioutil.TempDir(".", "kd-build")
	if err != nil {
		return err
	}
	defer os.RemoveAll(buildFolder)

	if b.ImportPath != "" {
		gopath := os.Getenv("GOPATH")
		if gopath == "" {
			return errors.New("GOPATH is not set")
		}

		// or use "go list <importPath>" for all packages and commands
		packages := []string{b.ImportPath}
		d, err := deps.LoadDeps(packages...)
		if err != nil {
			return err
		}

		err = d.InstallDeps()
		if err != nil {
			return err
		}

		buildFolder = filepath.Join(d.BuildGoPath, b.AppName)
	} else {
		err := util.Copy(b.BinaryPath, buildFolder)
		if err != nil {
			log.Println("copy assets", err)
		}
	}

	// include given files
	if b.Files != "" {
		files := strings.Split(b.Files, ",")
		for _, path := range files {
			err := util.Copy(path, buildFolder)
			if err != nil {
				log.Println("copy assets", err)
			}
		}
	}

	// create tar.gz file from final director
	tarFile := fmt.Sprintf("%s.%s-%s.tar.gz", b.AppName, runtime.GOOS, runtime.GOARCH)
	err = util.MakeTar(tarFile, buildFolder)
	if err != nil {
		return err
	}

	fmt.Printf("'%s' is created and ready for deploy\n", tarFile)
	return nil
}

// darwin is building a new .pkg installer for darwin based OS'es.
func (b *Build) darwin() error {
	version := b.Version
	if b.Output == "" {
		b.Output = fmt.Sprintf("kite-%s", b.AppName)
	}

	installRoot, err := ioutil.TempDir(".", "kd-build-darwin_")
	if err != nil {
		return err
	}
	defer os.RemoveAll(installRoot)

	buildFolder, err := ioutil.TempDir(".", "kd-build-darwin_")
	if err != nil {
		return err
	}
	defer os.RemoveAll(buildFolder)

	scriptDir := filepath.Join(buildFolder, "scripts")
	installRootUsr := filepath.Join(installRoot, "/usr/local/bin")

	os.MkdirAll(installRootUsr, 0755)
	err = util.Copy(b.BinaryPath, installRootUsr+"/"+b.AppName)
	if err != nil {
		return err
	}

	tempDest, err := ioutil.TempDir("", "tempDest")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tempDest)

	b.createScripts(scriptDir)
	b.createLaunchAgent(installRoot)

	cmdPkg := exec.Command("pkgbuild",
		"--identifier", fmt.Sprintf("%s.kite.%s.pkg", b.Identifier, b.AppName),
		"--version", version,
		"--scripts", scriptDir,
		"--root", installRoot,
		"--install-location", "/",
		fmt.Sprintf("%s/%s.kite.%s.pkg", tempDest, b.Identifier, b.AppName),
		// used for next step, also set up for distribution.xml
	)

	_, err = cmdPkg.CombinedOutput()
	if err != nil {
		return err
	}

	distributionFile := filepath.Join(buildFolder, "Distribution.xml")
	resources := filepath.Join(buildFolder, "Resources")

	targetFile := b.Output + ".pkg"

	b.createDistribution(distributionFile)

	cmdBuild := exec.Command("productbuild",
		"--distribution", distributionFile,
		"--resources", resources,
		"--package-path", tempDest,
		targetFile,
	)

	_, err = cmdBuild.CombinedOutput()
	if err != nil {
		return err
	}

	fmt.Printf("'%s' is created and ready for deploy\n", targetFile)
	return nil
}

func (b *Build) createLaunchAgent(rootDir string) {
	launchDir := fmt.Sprintf("%s/Library/LaunchAgents/", rootDir)
	os.MkdirAll(launchDir, 0700)

	launchFile := fmt.Sprintf("%s/%s.kite.%s.plist", launchDir, b.Identifier, b.AppName)

	lFile, err := os.Create(launchFile)
	if err != nil {
		log.Fatalln(err)
	}

	t := template.Must(template.New("launchAgent").Parse(launchAgent))
	t.Execute(lFile, b)

}

func (b *Build) createDistribution(file string) {
	distFile, err := os.Create(file)
	if err != nil {
		log.Fatalln(err)
	}

	t := template.Must(template.New("distribution").Parse(distribution))
	t.Execute(distFile, b)

}

func (b *Build) createScripts(scriptDir string) {
	os.MkdirAll(scriptDir, 0700) // does return nil if exists

	postInstallFile, err := os.Create(scriptDir + "/postInstall")
	if err != nil {
		log.Fatalln(err)
	}
	postInstallFile.Chmod(0755)

	preInstallFile, err := os.Create(scriptDir + "/preInstall")
	if err != nil {
		log.Fatalln(err)
	}
	preInstallFile.Chmod(0755)

	t := template.Must(template.New("postInstall").Parse(postInstall))
	t.Execute(postInstallFile, b)

	t = template.Must(template.New("preInstall").Parse(preInstall))
	t.Execute(preInstallFile, b)
}

func fileExist(dir string) bool {
	var err error
	_, err = os.Stat(dir)
	if err == nil {
		return true // file exist
	}

	if os.IsNotExist(err) {
		return false // file does not exist
	}

	panic(err) // permission errors or something else bad
}
<|endoftext|>


<commit_before>/*
Copyright 2015 Rohith All rights reserved.

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

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

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

package marathon

import (
	"fmt"
	"net/http"
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestErrors(t *testing.T) {
	tests := []struct {
		httpCode   int
		nameSuffix string
		errCode    int
		errText    string
		content    string
	}{
		// 400
		{
			httpCode: http.StatusBadRequest,
			errCode:  ErrCodeBadRequest,
			errText:  "Invalid JSON (path: '/id' errors: error.expected.jsstring, error.something.else; path: '/name' errors: error.not.inventive)",
			content:  content400(),
		},
		// 401
		{
			httpCode: http.StatusUnauthorized,
			errCode:  ErrCodeUnauthorized,
			errText:  "invalid username or password.",
			content:  `{"message": "invalid username or password."}`,
		},
		// 403
		{
			httpCode: http.StatusForbidden,
			errCode:  ErrCodeForbidden,
			errText:  "Not Authorized to perform this action!",
			content:  `{"message": "Not Authorized to perform this action!"}`,
		},
		// 404
		{
			httpCode: http.StatusNotFound,
			errCode:  ErrCodeNotFound,
			errText:  "App '/not_existent' does not exist",
			content:  `{"message": "App '/not_existent' does not exist"}`,
		},
		// 409 POST
		{
			httpCode:   http.StatusConflict,
			nameSuffix: "POST",
			errCode:    ErrCodeDuplicateID,
			errText:    "An app with id [/existing_app] already exists.",
			content:    `{"message": "An app with id [/existing_app] already exists."}`,
		},
		// 409 PUT
		{
			httpCode:   http.StatusConflict,
			nameSuffix: "PUT",
			errCode:    ErrCodeAppLocked,
			errText:    "App is locked (locking deployment IDs: 97c136bf-5a28-4821-9d94-480d9fbb01c8)",
			content:    `{"message":"App is locked", "deployments": [ { "id": "97c136bf-5a28-4821-9d94-480d9fbb01c8" } ] }`,
		},
		// 422 pre-1.0 "details" key
		{
			httpCode:   422,
			nameSuffix: "pre-1.0 details key",
			errCode:    ErrCodeInvalidBean,
			errText:    "Something is not valid (attribute 'upgradeStrategy.minimumHealthCapacity': is greater than 1; attribute 'foobar': foo does not have enough bar)",
			content:    content422("details"),
		},
		// 422 pre-1.0 "errors" key
		{
			httpCode:   422,
			nameSuffix: "pre-1.0 errors key",
			errCode:    ErrCodeInvalidBean,
			errText:    "Something is not valid (attribute 'upgradeStrategy.minimumHealthCapacity': is greater than 1; attribute 'foobar': foo does not have enough bar)",
			content:    content422("errors"),
		},
		// 422 1.0 "invalid object"
		{
			httpCode:   422,
			nameSuffix: "invalid object",
			errCode:    ErrCodeInvalidBean,
			errText:    "Object is not valid (path: 'upgradeStrategy.minimumHealthCapacity' errors: is greater than 1; path: '/value' errors: service port conflict app /app1, service port conflict app /app2)",
			content:    content422V1(),
		},
		// 499 unknown error
		{
			httpCode:   499,
			nameSuffix: "unknown error",
			errCode:    ErrCodeUnknown,
			errText:    "unknown error",
			content:    `{"message": "unknown error"}`,
		},
		// 500
		{
			httpCode: http.StatusInternalServerError,
			errCode:  ErrCodeServer,
			errText:  "internal server error",
			content:  `{"message": "internal server error"}`,
		},
		// 503 (no JSON)
		{
			httpCode:   http.StatusServiceUnavailable,
			nameSuffix: "no JSON",
			errCode:    ErrCodeServer,
			errText:    "No server is available to handle this request.",
			content:    `No server is available to handle this request.`,
		},
	}

	for _, test := range tests {
		name := fmt.Sprintf("%d", test.httpCode)
		if len(test.nameSuffix) > 0 {
			name = fmt.Sprintf("%s (%s)", name, test.nameSuffix)
		}
		apiErr := NewAPIError(test.httpCode, []byte(test.content))
		gotErrCode := apiErr.(*APIError).ErrCode
		assert.Equal(t, test.errCode, gotErrCode, fmt.Sprintf("HTTP code %s (error code): got %d, want %d", name, gotErrCode, test.errCode))
		pureErrText := strings.TrimPrefix(apiErr.Error(), "Marathon API error: ")
		assert.Equal(t, pureErrText, test.errText, fmt.Sprintf("HTTP code %s (error text)", name))
	}
}

func content400() string {
	return `{
	"message": "Invalid JSON",
	"details": [
	{
		"path": "/id",
		"errors": ["error.expected.jsstring", "error.something.else"]
	},
	{
		"path": "/name",
		"errors": ["error.not.inventive"]
	}
	]
}`
}

func content422(detailsPropKey string) string {
	return fmt.Sprintf(`{
	"message": "Something is not valid",
	"%s": [
		{
			"attribute": "upgradeStrategy.minimumHealthCapacity",
			"error": "is greater than 1"
		},
		{
			"attribute": "foobar",
			"error": "foo does not have enough bar"
		}
	]
}`, detailsPropKey)
}

func content422V1() string {
	return `{
	"message": "Object is not valid",
	"details": [
		{
			"path": "upgradeStrategy.minimumHealthCapacity",
			"errors": ["is greater than 1"]
		},
		{
			"path": "/value",
			"errors": ["service port conflict app /app1", "service port conflict app /app2"]
		}
	]
}`
}
<commit_msg>Fix indentation for HTTP 400 error JSON.<commit_after>/*
Copyright 2015 Rohith All rights reserved.

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

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

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

package marathon

import (
	"fmt"
	"net/http"
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestErrors(t *testing.T) {
	tests := []struct {
		httpCode   int
		nameSuffix string
		errCode    int
		errText    string
		content    string
	}{
		// 400
		{
			httpCode: http.StatusBadRequest,
			errCode:  ErrCodeBadRequest,
			errText:  "Invalid JSON (path: '/id' errors: error.expected.jsstring, error.something.else; path: '/name' errors: error.not.inventive)",
			content:  content400(),
		},
		// 401
		{
			httpCode: http.StatusUnauthorized,
			errCode:  ErrCodeUnauthorized,
			errText:  "invalid username or password.",
			content:  `{"message": "invalid username or password."}`,
		},
		// 403
		{
			httpCode: http.StatusForbidden,
			errCode:  ErrCodeForbidden,
			errText:  "Not Authorized to perform this action!",
			content:  `{"message": "Not Authorized to perform this action!"}`,
		},
		// 404
		{
			httpCode: http.StatusNotFound,
			errCode:  ErrCodeNotFound,
			errText:  "App '/not_existent' does not exist",
			content:  `{"message": "App '/not_existent' does not exist"}`,
		},
		// 409 POST
		{
			httpCode:   http.StatusConflict,
			nameSuffix: "POST",
			errCode:    ErrCodeDuplicateID,
			errText:    "An app with id [/existing_app] already exists.",
			content:    `{"message": "An app with id [/existing_app] already exists."}`,
		},
		// 409 PUT
		{
			httpCode:   http.StatusConflict,
			nameSuffix: "PUT",
			errCode:    ErrCodeAppLocked,
			errText:    "App is locked (locking deployment IDs: 97c136bf-5a28-4821-9d94-480d9fbb01c8)",
			content:    `{"message":"App is locked", "deployments": [ { "id": "97c136bf-5a28-4821-9d94-480d9fbb01c8" } ] }`,
		},
		// 422 pre-1.0 "details" key
		{
			httpCode:   422,
			nameSuffix: "pre-1.0 details key",
			errCode:    ErrCodeInvalidBean,
			errText:    "Something is not valid (attribute 'upgradeStrategy.minimumHealthCapacity': is greater than 1; attribute 'foobar': foo does not have enough bar)",
			content:    content422("details"),
		},
		// 422 pre-1.0 "errors" key
		{
			httpCode:   422,
			nameSuffix: "pre-1.0 errors key",
			errCode:    ErrCodeInvalidBean,
			errText:    "Something is not valid (attribute 'upgradeStrategy.minimumHealthCapacity': is greater than 1; attribute 'foobar': foo does not have enough bar)",
			content:    content422("errors"),
		},
		// 422 1.0 "invalid object"
		{
			httpCode:   422,
			nameSuffix: "invalid object",
			errCode:    ErrCodeInvalidBean,
			errText:    "Object is not valid (path: 'upgradeStrategy.minimumHealthCapacity' errors: is greater than 1; path: '/value' errors: service port conflict app /app1, service port conflict app /app2)",
			content:    content422V1(),
		},
		// 499 unknown error
		{
			httpCode:   499,
			nameSuffix: "unknown error",
			errCode:    ErrCodeUnknown,
			errText:    "unknown error",
			content:    `{"message": "unknown error"}`,
		},
		// 500
		{
			httpCode: http.StatusInternalServerError,
			errCode:  ErrCodeServer,
			errText:  "internal server error",
			content:  `{"message": "internal server error"}`,
		},
		// 503 (no JSON)
		{
			httpCode:   http.StatusServiceUnavailable,
			nameSuffix: "no JSON",
			errCode:    ErrCodeServer,
			errText:    "No server is available to handle this request.",
			content:    `No server is available to handle this request.`,
		},
	}

	for _, test := range tests {
		name := fmt.Sprintf("%d", test.httpCode)
		if len(test.nameSuffix) > 0 {
			name = fmt.Sprintf("%s (%s)", name, test.nameSuffix)
		}
		apiErr := NewAPIError(test.httpCode, []byte(test.content))
		gotErrCode := apiErr.(*APIError).ErrCode
		assert.Equal(t, test.errCode, gotErrCode, fmt.Sprintf("HTTP code %s (error code): got %d, want %d", name, gotErrCode, test.errCode))
		pureErrText := strings.TrimPrefix(apiErr.Error(), "Marathon API error: ")
		assert.Equal(t, pureErrText, test.errText, fmt.Sprintf("HTTP code %s (error text)", name))
	}
}

func content400() string {
	return `{
	"message": "Invalid JSON",
	"details": [
		{
			"path": "/id",
			"errors": ["error.expected.jsstring", "error.something.else"]
		},
		{
			"path": "/name",
			"errors": ["error.not.inventive"]
		}
	]
}`
}

func content422(detailsPropKey string) string {
	return fmt.Sprintf(`{
	"message": "Something is not valid",
	"%s": [
		{
			"attribute": "upgradeStrategy.minimumHealthCapacity",
			"error": "is greater than 1"
		},
		{
			"attribute": "foobar",
			"error": "foo does not have enough bar"
		}
	]
}`, detailsPropKey)
}

func content422V1() string {
	return `{
	"message": "Object is not valid",
	"details": [
		{
			"path": "upgradeStrategy.minimumHealthCapacity",
			"errors": ["is greater than 1"]
		},
		{
			"path": "/value",
			"errors": ["service port conflict app /app1", "service port conflict app /app2"]
		}
	]
}`
}
<|endoftext|>


<commit_before>package es

import (
	"log"
	"os"
	"time"
)

var timer = time.NewTimer(1 * time.Second)

type IndexerStats struct {
	Runs        int64
	IndexedDocs int64
	TotalTime   time.Duration
	started     time.Time
}

func (stats *IndexerStats) Add(count int, dur time.Duration) {
	if stats.started.IsZero() {
		stats.started = time.Now()
	}
	stats.Runs++
	stats.IndexedDocs += int64(count)
	stats.TotalTime += dur
}

type Indexer struct {
	Index *Index

	IndexEvery time.Duration // triggers a new index run after that duration, will be reset when BatchSize reached
	BatchSize  int           // triggers a new index run when the batch reaches that size

	docsBatch   []*Doc
	docsChannel chan *Doc
	timer       *time.Timer
	Stats       IndexerStats
}

func (indexer *Indexer) Finish() error {
	return indexer.indexBatch()
}

func (indexer *Indexer) resetBatch() {
	indexer.docsBatch = make([]*Doc, 0, indexer.BatchSize)
}

func (indexer *Indexer) resetTimer() bool {
	return indexer.timer.Reset(indexer.IndexEvery)
}

var logger = log.New(os.Stderr, "", 0)

// TODO change handling to e.g. Add command with implizit opening of channel
// to not expose the channel to the public
func (indexer *Indexer) Start() chan *Doc {
	if indexer.BatchSize == 0 {
		indexer.BatchSize = 100
	}
	if indexer.IndexEvery == 0 {
		indexer.IndexEvery = 1 * time.Hour
	}
	indexer.timer = time.NewTimer(indexer.IndexEvery)
	indexer.docsChannel = make(chan *Doc, indexer.BatchSize)
	indexer.resetBatch()
	go func(indexer *Indexer) {
		for {
			select {
			case <-indexer.timer.C:
				e := indexer.indexBatch()
				if e != nil {
					logger.Printf("ERROR=%q", e)
				}
				indexer.resetTimer()
			case doc, ok := <-indexer.docsChannel:
				if !ok {
					indexer.timer.Stop()
					e := indexer.indexBatch()
					if e != nil {
						logger.Printf("ERROR=%q", e)
					}
					return
				}
				if doc.Index == "" {
					doc.Index = indexer.Index.Index
				}
				if doc.Type == "" {
					doc.Type = indexer.Index.Type
				}
				indexer.docsBatch = append(indexer.docsBatch, doc)
				if len(indexer.docsBatch) >= indexer.BatchSize {
					indexer.timer.Stop()
					e := indexer.indexBatch()
					if e != nil {
						logger.Printf("ERROR: %s", e)
					}
					indexer.resetTimer()
				}
			}
		}
	}(indexer)
	return indexer.docsChannel
}

func (indexer *Indexer) Close() error {
	if indexer.docsChannel != nil {
		close(indexer.docsChannel)
	}
	return indexer.indexBatch()
}

func (indexer *Indexer) indexBatch() error {
	if len(indexer.docsBatch) < 1 {
		return nil
	}
	started := time.Now()
	e := indexer.Index.IndexDocs(indexer.docsBatch)
	if e != nil {
		return e
	}
	indexer.Stats.Add(len(indexer.docsBatch), time.Now().Sub(started))
	indexer.resetBatch()
	return nil
}
<commit_msg>make *IndexerStats a reference<commit_after>package es

import (
	"log"
	"os"
	"time"
)

var timer = time.NewTimer(1 * time.Second)

type IndexerStats struct {
	Runs        int64
	IndexedDocs int64
	TotalTime   time.Duration
	started     time.Time
}

func (stats *IndexerStats) Add(count int, dur time.Duration) {
	if stats.started.IsZero() {
		stats.started = time.Now()
	}
	stats.Runs++
	stats.IndexedDocs += int64(count)
	stats.TotalTime += dur
}

type Indexer struct {
	Index *Index

	IndexEvery time.Duration // triggers a new index run after that duration, will be reset when BatchSize reached
	BatchSize  int           // triggers a new index run when the batch reaches that size

	docsBatch   []*Doc
	docsChannel chan *Doc
	timer       *time.Timer
	Stats       *IndexerStats
}

func (indexer *Indexer) Finish() error {
	return indexer.indexBatch()
}

func (indexer *Indexer) resetBatch() {
	indexer.docsBatch = make([]*Doc, 0, indexer.BatchSize)
}

func (indexer *Indexer) resetTimer() bool {
	return indexer.timer.Reset(indexer.IndexEvery)
}

var logger = log.New(os.Stderr, "", 0)

// TODO change handling to e.g. Add command with implizit opening of channel
// to not expose the channel to the public
func (indexer *Indexer) Start() chan *Doc {
	if indexer.BatchSize == 0 {
		indexer.BatchSize = 100
	}
	if indexer.IndexEvery == 0 {
		indexer.IndexEvery = 1 * time.Hour
	}
	indexer.timer = time.NewTimer(indexer.IndexEvery)
	indexer.docsChannel = make(chan *Doc, indexer.BatchSize)
	indexer.resetBatch()
	go func(indexer *Indexer) {
		for {
			select {
			case <-indexer.timer.C:
				e := indexer.indexBatch()
				if e != nil {
					logger.Printf("ERROR=%q", e)
				}
				indexer.resetTimer()
			case doc, ok := <-indexer.docsChannel:
				if !ok {
					indexer.timer.Stop()
					e := indexer.indexBatch()
					if e != nil {
						logger.Printf("ERROR=%q", e)
					}
					return
				}
				if doc.Index == "" {
					doc.Index = indexer.Index.Index
				}
				if doc.Type == "" {
					doc.Type = indexer.Index.Type
				}
				indexer.docsBatch = append(indexer.docsBatch, doc)
				if len(indexer.docsBatch) >= indexer.BatchSize {
					indexer.timer.Stop()
					e := indexer.indexBatch()
					if e != nil {
						logger.Printf("ERROR: %s", e)
					}
					indexer.resetTimer()
				}
			}
		}
	}(indexer)
	return indexer.docsChannel
}

func (indexer *Indexer) Close() error {
	if indexer.docsChannel != nil {
		close(indexer.docsChannel)
	}
	return indexer.indexBatch()
}

func (indexer *Indexer) indexBatch() error {
	if len(indexer.docsBatch) < 1 {
		return nil
	}
	started := time.Now()
	e := indexer.Index.IndexDocs(indexer.docsBatch)
	if e != nil {
		return e
	}
	indexer.Stats.Add(len(indexer.docsBatch), time.Now().Sub(started))
	indexer.resetBatch()
	return nil
}
<|endoftext|>


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

package nvimutil

import (
	"bytes"

	"fmt"
	"go/token"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"nvim-go/config"
	"nvim-go/context"
	"nvim-go/pathutil"

	"github.com/neovim/go-client/nvim"
	"github.com/pkg/errors"
)

// SetLoclist set the error results data to current buffer's locationlist.
func SetLoclist(v *nvim.Nvim, loclist []*nvim.QuickfixError) error {
	// setloclist({nr}, {list} [, {action}])
	// v.Call(fname string, result interface{}, args ...interface{})
	if len(loclist) > 0 {
		v.Call("setloclist", nil, 0, loclist)
	} else {
		v.Command("lexpr ''")
	}

	return nil
}

var (
	listtype     ErrorListType
	openlistCmd  func() error
	closelistCmd func() error
	clearlistCmd func() error
	setlistCmd   func(errlist []*nvim.QuickfixError) error
)

type ErrorListType string

const (
	Quickfix     ErrorListType = "quickfix"
	LocationList               = "locationlist"
)

func getListCmd(v *nvim.Nvim) {
	if listtype == "" {
		listtype = ErrorListType(config.ErrorListType)
	}
	switch listtype {
	case Quickfix:
		openlistCmd = func() error { return v.Command("copen") }
		closelistCmd = func() error { return v.Command("cclose") }
		clearlistCmd = func() error { return v.Command("cgetexpr ''") }
		setlistCmd = func(errlist []*nvim.QuickfixError) error { return v.Call("setqflist", nil, errlist, "r") }
	case LocationList:
		openlistCmd = func() error { return v.Command("lopen") }
		closelistCmd = func() error { return v.Command("lclose") }
		clearlistCmd = func() error { return v.Command("lgetexpr ''") }
		setlistCmd = func(errlist []*nvim.QuickfixError) error { return v.Call("setloclist", nil, 0, errlist, "r") }
	}
}

// ErrorList merges the errlist map items and open the locationlist window.
// TODO(zchee): This function will reports the errors with open the quickfix window, but will close
// the quickfix window if no errors.
// Do ErrorList function name is appropriate?
func ErrorList(v *nvim.Nvim, errors map[string][]*nvim.QuickfixError, keep bool) error {
	if listtype == "" {
		getListCmd(v)
	}

	if errors == nil || len(errors) == 0 {
		defer clearlistCmd()
		return closelistCmd()
	}

	var errlist []*nvim.QuickfixError
	for _, err := range errors {
		errlist = append(errlist, err...)
	}
	if err := SetErrorlist(v, errlist); err != nil {
		return err
	}

	if keep {
		w, err := v.CurrentWindow()
		if err != nil {
			return err
		}
		defer v.SetCurrentWindow(w)
	}
	return openlistCmd()
}

// SetErrorlist set the error results data to Neovim error list.
func SetErrorlist(v *nvim.Nvim, errlist []*nvim.QuickfixError) error {
	if setlistCmd == nil {
		getListCmd(v)
	}

	return setlistCmd(errlist)
}

// ClearErrorlist clear the Neovim error list.
func ClearErrorlist(v *nvim.Nvim, close bool) error {
	if clearlistCmd == nil {
		getListCmd(v)
	}

	if close {
		defer closelistCmd()
	}
	return clearlistCmd()
}

// OpenLoclist open or close the current buffer's locationlist window.
func OpenLoclist(v *nvim.Nvim, w nvim.Window, loclist []*nvim.QuickfixError, keep bool) error {
	if len(loclist) == 0 {
		return v.Command("lclose")
	}

	v.Command("lopen")
	if keep {
		return v.SetCurrentWindow(w)
	}
	return nil
}

// CloseLoclist close the current buffer's locationlist window.
func CloseLoclist(v *nvim.Nvim) error {
	return v.Command("lclose")
}

// SetQuickfix set the error results data to quickfix list.
func SetQuickfix(p *nvim.Pipeline, qflist []*nvim.QuickfixError) error {
	p.Call("setqflist", nil, qflist)

	return nil
}

// OpenOuickfix open the quickfix list window.
func OpenOuickfix(p *nvim.Pipeline, w nvim.Window, keep bool) error {
	p.Command("copen")
	if keep {
		p.SetCurrentWindow(w)
	}
	if err := p.Wait(); err != nil {
		return err
	}

	return nil
}

// CloseQuickfix close the quickfix list window.
func CloseQuickfix(v *nvim.Nvim) error {
	return v.Command("cclose")
}

func GotoPos(v *nvim.Nvim, w nvim.Window, pos token.Position, cwd string) error {
	fname, line, col := SplitPos(pos.String(), cwd)

	v.Command(fmt.Sprintf("edit %s", fname))
	v.SetWindowCursor(w, [2]int{line, col - 1})
	defer v.Command(`lclose`)

	return v.Command(`normal zz`)
}

// SplitPos parses a string of form 'token.Pos', and return the relative
// filepath from the current working directory path.
func SplitPos(pos string, cwd string) (string, int, int) {
	position := strings.Split(pos, ":")

	fname := position[0]
	line, err := strconv.ParseInt(position[1], 10, 64)
	if err != nil {
		line = 0
	}
	col, err := strconv.ParseInt(position[2], 10, 64)
	if err != nil {
		col = 0
	}

	if strings.HasPrefix(fname, cwd) {
		frel := strings.TrimPrefix(fname, cwd+string(filepath.Separator))
		if fname != frel {
			return frel, int(line), int(col)
		}
	}

	return fname, int(line), int(col)
}

// regexp pattern: https://regex101.com/r/bUVZpH/2
var errRe = regexp.MustCompile(`(?m)^(?:#\s([[:graph:]]+))?(?:[\s\t]+)?([^\s:]+):(\d+)(?::(\d+))?(?::)?\s(.*)`)

// ParseError parses a typical Go tools error messages.
func ParseError(errs []byte, cwd string, ctxt *context.Build) ([]*nvim.QuickfixError, error) {
	var (
		// packagePath for the save the error files parent directory.
		// It will be re-assigned if "# " is in the error message.
		packagePath string
		errlist     []*nvim.QuickfixError
	)

	// m[1]: package path with "# " prefix
	// m[2]: error files relative path
	// m[3]: line number of error point
	// m[4]: column number of error point
	// m[5]: error description text
	for _, m := range errRe.FindAllSubmatch(errs, -1) {
		if m[1] != nil {
			// Save the package path for the second subsequent errors
			packagePath = string(m[1])
		}
		filename := string(m[2])

		// Avoid the local package error. like "package foo" and edit "cmd/foo/main.go"
		if !strings.Contains(filename, "../") {
			if !filepath.IsAbs(filename) && packagePath != "" {
				// Joins the packagePath and error file
				filename = filepath.Join(packagePath, filepath.Base(filename))
			}

			// Cleanup filename to relative path of current working directory
			switch ctxt.Tool {
			case "go":
				var sep string
				switch {
				// filename has not directory path
				case filepath.Dir(filename) == ".":
					filename = filepath.Join(cwd, filename)

				// not contains '#' package title in errror
				case strings.HasPrefix(filename, cwd):
					sep = cwd
					filename = strings.TrimPrefix(filename, sep+string(filepath.Separator))

				// filename is like "github.com/foo/bar.go"
				case strings.HasPrefix(filename, pathutil.TrimGoPath(cwd)):
					sep = pathutil.TrimGoPath(cwd) + string(filepath.Separator)
					filename = strings.TrimPrefix(filename, sep)
				}
			case "gb":
				// filename has not directory path
				if !filepath.IsAbs(filename) {
					filename = filepath.Join(ctxt.ProjectRoot, "src", filename)
				}
			default:
				return nil, errors.New("unknown compiler tool")
			}
		}

		// Finally, try to convert the relative path from cwd
		filename = pathutil.Rel(cwd, filename)

		// line is necessary for error messages
		line, err := strconv.Atoi(string(m[3]))
		if err != nil {
			return nil, err
		}

		// Ignore err because fail strconv.Atoi will assign 0 to col
		col, _ := strconv.Atoi(string(m[4]))

		errlist = append(errlist, &nvim.QuickfixError{
			FileName: filename,
			LNum:     line,
			Col:      col,
			Text:     string(bytes.TrimSpace(m[5])),
		})
	}

	return errlist, nil
}
<commit_msg>nvimutil/locationlist: Fix wrong inline comment<commit_after>// Copyright 2016 The nvim-go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package nvimutil

import (
	"bytes"

	"fmt"
	"go/token"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"

	"nvim-go/config"
	"nvim-go/context"
	"nvim-go/pathutil"

	"github.com/neovim/go-client/nvim"
	"github.com/pkg/errors"
)

// SetLoclist set the error results data to current buffer's locationlist.
func SetLoclist(v *nvim.Nvim, loclist []*nvim.QuickfixError) error {
	// setloclist({nr}, {list} [, {action}])
	// v.Call(fname string, result interface{}, args ...interface{})
	if len(loclist) > 0 {
		v.Call("setloclist", nil, 0, loclist)
	} else {
		v.Command("lexpr ''")
	}

	return nil
}

var (
	listtype     ErrorListType
	openlistCmd  func() error
	closelistCmd func() error
	clearlistCmd func() error
	setlistCmd   func(errlist []*nvim.QuickfixError) error
)

type ErrorListType string

const (
	Quickfix     ErrorListType = "quickfix"
	LocationList               = "locationlist"
)

func getListCmd(v *nvim.Nvim) {
	if listtype == "" {
		listtype = ErrorListType(config.ErrorListType)
	}
	switch listtype {
	case Quickfix:
		openlistCmd = func() error { return v.Command("copen") }
		closelistCmd = func() error { return v.Command("cclose") }
		clearlistCmd = func() error { return v.Command("cgetexpr ''") }
		setlistCmd = func(errlist []*nvim.QuickfixError) error { return v.Call("setqflist", nil, errlist, "r") }
	case LocationList:
		openlistCmd = func() error { return v.Command("lopen") }
		closelistCmd = func() error { return v.Command("lclose") }
		clearlistCmd = func() error { return v.Command("lgetexpr ''") }
		setlistCmd = func(errlist []*nvim.QuickfixError) error { return v.Call("setloclist", nil, 0, errlist, "r") }
	}
}

// ErrorList merges the errlist map items and open the locationlist window.
// TODO(zchee): This function will reports the errors with open the quickfix window, but will close
// the quickfix window if no errors.
// Do ErrorList function name is appropriate?
func ErrorList(v *nvim.Nvim, errors map[string][]*nvim.QuickfixError, keep bool) error {
	if listtype == "" {
		getListCmd(v)
	}

	if errors == nil || len(errors) == 0 {
		defer clearlistCmd()
		return closelistCmd()
	}

	var errlist []*nvim.QuickfixError
	for _, err := range errors {
		errlist = append(errlist, err...)
	}
	if err := SetErrorlist(v, errlist); err != nil {
		return err
	}

	if keep {
		w, err := v.CurrentWindow()
		if err != nil {
			return err
		}
		defer v.SetCurrentWindow(w)
	}
	return openlistCmd()
}

// SetErrorlist set the error results data to Neovim error list.
func SetErrorlist(v *nvim.Nvim, errlist []*nvim.QuickfixError) error {
	if setlistCmd == nil {
		getListCmd(v)
	}

	return setlistCmd(errlist)
}

// ClearErrorlist clear the Neovim error list.
func ClearErrorlist(v *nvim.Nvim, close bool) error {
	if clearlistCmd == nil {
		getListCmd(v)
	}

	if close {
		defer closelistCmd()
	}
	return clearlistCmd()
}

// OpenLoclist open or close the current buffer's locationlist window.
func OpenLoclist(v *nvim.Nvim, w nvim.Window, loclist []*nvim.QuickfixError, keep bool) error {
	if len(loclist) == 0 {
		return v.Command("lclose")
	}

	v.Command("lopen")
	if keep {
		return v.SetCurrentWindow(w)
	}
	return nil
}

// CloseLoclist close the current buffer's locationlist window.
func CloseLoclist(v *nvim.Nvim) error {
	return v.Command("lclose")
}

// SetQuickfix set the error results data to quickfix list.
func SetQuickfix(p *nvim.Pipeline, qflist []*nvim.QuickfixError) error {
	p.Call("setqflist", nil, qflist)

	return nil
}

// OpenOuickfix open the quickfix list window.
func OpenOuickfix(p *nvim.Pipeline, w nvim.Window, keep bool) error {
	p.Command("copen")
	if keep {
		p.SetCurrentWindow(w)
	}
	if err := p.Wait(); err != nil {
		return err
	}

	return nil
}

// CloseQuickfix close the quickfix list window.
func CloseQuickfix(v *nvim.Nvim) error {
	return v.Command("cclose")
}

func GotoPos(v *nvim.Nvim, w nvim.Window, pos token.Position, cwd string) error {
	fname, line, col := SplitPos(pos.String(), cwd)

	v.Command(fmt.Sprintf("edit %s", fname))
	v.SetWindowCursor(w, [2]int{line, col - 1})
	defer v.Command(`lclose`)

	return v.Command(`normal zz`)
}

// SplitPos parses a string of form 'token.Pos', and return the relative
// filepath from the current working directory path.
func SplitPos(pos string, cwd string) (string, int, int) {
	position := strings.Split(pos, ":")

	fname := position[0]
	line, err := strconv.ParseInt(position[1], 10, 64)
	if err != nil {
		line = 0
	}
	col, err := strconv.ParseInt(position[2], 10, 64)
	if err != nil {
		col = 0
	}

	if strings.HasPrefix(fname, cwd) {
		frel := strings.TrimPrefix(fname, cwd+string(filepath.Separator))
		if fname != frel {
			return frel, int(line), int(col)
		}
	}

	return fname, int(line), int(col)
}

// regexp pattern: https://regex101.com/r/bUVZpH/2
var errRe = regexp.MustCompile(`(?m)^(?:#\s([[:graph:]]+))?(?:[\s\t]+)?([^\s:]+):(\d+)(?::(\d+))?(?::)?\s(.*)`)

// ParseError parses a typical Go tools error messages.
func ParseError(errs []byte, cwd string, ctxt *context.Build) ([]*nvim.QuickfixError, error) {
	var (
		// packagePath for the save the error files parent directory.
		// It will be re-assigned if "# " is in the error message.
		packagePath string
		errlist     []*nvim.QuickfixError
	)

	// m[1]: package path with "# " prefix
	// m[2]: error files relative path
	// m[3]: line number of error point
	// m[4]: column number of error point
	// m[5]: error description text
	for _, m := range errRe.FindAllSubmatch(errs, -1) {
		if m[1] != nil {
			// Save the package path for the second subsequent errors
			packagePath = string(m[1])
		}
		filename := string(m[2])

		// Avoid the local package error. like "package foo" and edit "cmd/foo/main.go"
		if !strings.Contains(filename, "../") {
			if !filepath.IsAbs(filename) && packagePath != "" {
				// Joins the packagePath and error file
				filename = filepath.Join(packagePath, filepath.Base(filename))
			}

			// Cleanup filename to relative path of current working directory
			switch ctxt.Tool {
			case "go":
				var sep string
				switch {
				// filename has not directory path
				case filepath.Dir(filename) == ".":
					filename = filepath.Join(cwd, filename)

				// not contains '#' package title in errror
				case strings.HasPrefix(filename, cwd):
					sep = cwd
					filename = strings.TrimPrefix(filename, sep+string(filepath.Separator))

				// filename is like "github.com/foo/bar.go"
				case strings.HasPrefix(filename, pathutil.TrimGoPath(cwd)):
					sep = pathutil.TrimGoPath(cwd) + string(filepath.Separator)
					filename = strings.TrimPrefix(filename, sep)
				}
			case "gb":
				// gb compiler error messages is relative filename path of project root dir
				if !filepath.IsAbs(filename) {
					filename = filepath.Join(ctxt.ProjectRoot, "src", filename)
				}
			default:
				return nil, errors.New("unknown compiler tool")
			}
		}

		// Finally, try to convert the relative path from cwd
		filename = pathutil.Rel(cwd, filename)

		// line is necessary for error messages
		line, err := strconv.Atoi(string(m[3]))
		if err != nil {
			return nil, err
		}

		// Ignore err because fail strconv.Atoi will assign 0 to col
		col, _ := strconv.Atoi(string(m[4]))

		errlist = append(errlist, &nvim.QuickfixError{
			FileName: filename,
			LNum:     line,
			Col:      col,
			Text:     string(bytes.TrimSpace(m[5])),
		})
	}

	return errlist, nil
}
<|endoftext|>


<commit_before>package tlstext

import (
	"testing"
)

func TestCipherSuite(t *testing.T) {
	value := uint16(0xc02b)
	expected := "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
	actual := CipherSuite(value)
	if expected != actual  {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}

	value = uint16(1234)
	expected = ""
	actual = CipherSuite(value)
	if expected != actual  {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}
}

func TestVersion(t *testing.T) {
	value := uint16(0x0303)
	expected := "TLS12"
	actual := Version(value)
	if expected != actual  {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}

	value = uint16(1234)
	expected = ""
	actual = Version(value)
	if expected != actual  {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}
}
<commit_msg>gofmt<commit_after>package tlstext

import (
	"testing"
)

func TestCipherSuite(t *testing.T) {
	value := uint16(0xc02b)
	expected := "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
	actual := CipherSuite(value)
	if expected != actual {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}

	value = uint16(1234)
	expected = ""
	actual = CipherSuite(value)
	if expected != actual {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}
}

func TestVersion(t *testing.T) {
	value := uint16(0x0303)
	expected := "TLS12"
	actual := Version(value)
	if expected != actual {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}

	value = uint16(1234)
	expected = ""
	actual = Version(value)
	if expected != actual {
		t.Errorf("For %d, expected %q got %q", value, expected, actual)
	}
}
<|endoftext|>


<commit_before>package timeout

// ExitStatus stores exit information of the command
type ExitStatus struct {
	Code     int
	Signaled bool
	typ      exitType
}

// IsTimedOut returns the command timed out or not
func (ex *ExitStatus) IsTimedOut() bool {
	return ex.typ == exitTypeTimedOut || ex.typ == exitTypeKilled
}

// IsKilled returns the command is killed or not
func (ex *ExitStatus) IsKilled() bool {
	return ex.Code == 137 && ex.Signaled
}

// GetExitCode gets the exit code for command line tools
func (ex *ExitStatus) GetExitCode() int {
	switch {
	case ex.IsKilled():
		return exitKilled
	case ex.IsTimedOut():
		return exitTimedOut
	default:
		return ex.Code
	}
}

// GetChildExitCode gets the exit code of the Cmd itself
func (ex *ExitStatus) GetChildExitCode() int {
	return ex.Code
}

type exitType int

// exit types
const (
	exitTypeNormal exitType = iota
	exitTypeTimedOut
	exitTypeKilled
	exitTypeCanceled
)
<commit_msg>IsCanceled<commit_after>package timeout

// ExitStatus stores exit information of the command
type ExitStatus struct {
	Code     int
	Signaled bool
	typ      exitType
}

// IsTimedOut returns the command timed out or not
func (ex *ExitStatus) IsTimedOut() bool {
	return ex.typ == exitTypeTimedOut || ex.typ == exitTypeKilled
}

// IsCanceled return if the command canceled by context or not
func (ex *ExitStatus) IsCanceled() bool {
	return ex.typ == exitTypeCanceled
}

// IsKilled returns the command is killed or not
func (ex *ExitStatus) IsKilled() bool {
	return ex.Code == 137 && ex.Signaled
}

// GetExitCode gets the exit code for command line tools
func (ex *ExitStatus) GetExitCode() int {
	switch {
	case ex.IsKilled():
		return exitKilled
	case ex.IsTimedOut():
		return exitTimedOut
	default:
		return ex.Code
	}
}

// GetChildExitCode gets the exit code of the Cmd itself
func (ex *ExitStatus) GetChildExitCode() int {
	return ex.Code
}

type exitType int

// exit types
const (
	exitTypeNormal exitType = iota
	exitTypeTimedOut
	exitTypeKilled
	exitTypeCanceled
)
<|endoftext|>