<commit_before>package cmd

import (
	"fmt"
	"io"
	"os"

	"github.com/cozy/cozy-stack/pkg/config"
	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/spf13/cobra"
)

var flagSwiftObjectContentType string

var swiftCmdGroup = &cobra.Command{
	Use:   "swift <command>",
	Short: "Interact directly with OpenStack Swift object storage",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		if err := config.Setup(cfgFile); err != nil {
			return err
		}
		if config.FsURL().Scheme != config.SchemeSwift {
			return fmt.Errorf("swift: the configured filesystem does not rely on OpenStack Swift")
		}
		return config.InitSwiftConnection(config.FsURL())
	},
	RunE: func(cmd *cobra.Command, args []string) error {
		return cmd.Usage()
	},
}

var swiftGetCmd = &cobra.Command{
	Use: "get <domain> <object-name>",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 2 {
			return cmd.Usage()
		}
		i, err := instance.Get(args[0])
		if err != nil {
			return err
		}
		sc := config.GetSwiftConnection()
		objectName := args[1]
		f, _, err := sc.ObjectOpen(swiftContainer(i), objectName, false, nil)
		if err != nil {
			return err
		}
		_, err = io.Copy(os.Stdout, f)
		if err != nil {
			return err
		}
		return f.Close()
	},
}

var swiftPutCmd = &cobra.Command{
	Use: "put <domain> <object-name>",
	Long: `cozy-stack swift put can be used to create or update an object in
the swift container associated to the given domain. The content of the file is
expected on the standard input.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 2 {
			return cmd.Usage()
		}
		i, err := instance.Get(args[0])
		if err != nil {
			return err
		}
		sc := config.GetSwiftConnection()
		objectName := args[1]
		f, err := sc.ObjectCreate(swiftContainer(i), objectName, true, "", flagSwiftObjectContentType, nil)
		if err != nil {
			return err
		}
		_, err = io.Copy(f, os.Stdin)
		if err != nil {
			return nil
		}
		return f.Close()
	},
}

var swiftDeleteCmd = &cobra.Command{
	Use:     "rm <domain> <object-name>",
	Aliases: []string{"delete"},
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 2 {
			return cmd.Usage()
		}
		i, err := instance.Get(args[0])
		if err != nil {
			return err
		}
		sc := config.GetSwiftConnection()
		objectName := args[1]
		return sc.ObjectDelete(swiftContainer(i), objectName)
	},
}

func swiftContainer(i *instance.Instance) string {
	if i.SwiftCluster > 0 {
		return "cozy-v2-" + i.DBPrefix()
	}
	return "cozy-" + i.DBPrefix()
}

func init() {
	swiftPutCmd.Flags().StringVar(&flagSwiftObjectContentType, "content-type", "", "Specify a Content-Type for the created object")

	swiftCmdGroup.AddCommand(swiftGetCmd)
	swiftCmdGroup.AddCommand(swiftPutCmd)
	swiftCmdGroup.AddCommand(swiftDeleteCmd)

	RootCmd.AddCommand(swiftCmdGroup)
}
<commit_msg>Add a swift ls command to list objects<commit_after>package cmd

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/cozy/cozy-stack/pkg/config"
	"github.com/cozy/cozy-stack/pkg/instance"
	"github.com/cozy/swift"
	"github.com/spf13/cobra"
)

var flagSwiftObjectContentType string

var swiftCmdGroup = &cobra.Command{
	Use:   "swift <command>",
	Short: "Interact directly with OpenStack Swift object storage",
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		if err := config.Setup(cfgFile); err != nil {
			return err
		}
		if config.FsURL().Scheme != config.SchemeSwift {
			return fmt.Errorf("swift: the configured filesystem does not rely on OpenStack Swift")
		}
		return config.InitSwiftConnection(config.FsURL())
	},
	RunE: func(cmd *cobra.Command, args []string) error {
		return cmd.Usage()
	},
}

var swiftGetCmd = &cobra.Command{
	Use: "get <domain> <object-name>",
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 2 {
			return cmd.Usage()
		}
		i, err := instance.Get(args[0])
		if err != nil {
			return err
		}
		sc := config.GetSwiftConnection()
		objectName := args[1]
		f, _, err := sc.ObjectOpen(swiftContainer(i), objectName, false, nil)
		if err != nil {
			return err
		}
		_, err = io.Copy(os.Stdout, f)
		if err != nil {
			return err
		}
		return f.Close()
	},
}

var swiftPutCmd = &cobra.Command{
	Use: "put <domain> <object-name>",
	Long: `cozy-stack swift put can be used to create or update an object in
the swift container associated to the given domain. The content of the file is
expected on the standard input.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 2 {
			return cmd.Usage()
		}
		i, err := instance.Get(args[0])
		if err != nil {
			return err
		}
		sc := config.GetSwiftConnection()
		objectName := args[1]
		f, err := sc.ObjectCreate(swiftContainer(i), objectName, true, "", flagSwiftObjectContentType, nil)
		if err != nil {
			return err
		}
		_, err = io.Copy(f, os.Stdin)
		if err != nil {
			return nil
		}
		return f.Close()
	},
}

var swiftDeleteCmd = &cobra.Command{
	Use:     "rm <domain> <object-name>",
	Aliases: []string{"delete"},
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 2 {
			return cmd.Usage()
		}
		i, err := instance.Get(args[0])
		if err != nil {
			return err
		}
		sc := config.GetSwiftConnection()
		objectName := args[1]
		return sc.ObjectDelete(swiftContainer(i), objectName)
	},
}

var swiftLsCmd = &cobra.Command{
	Use:     "ls <domain>",
	Aliases: []string{"delete"},
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) < 1 {
			return cmd.Usage()
		}
		i, err := instance.Get(args[0])
		if err != nil {
			return err
		}
		sc := config.GetSwiftConnection()
		container := swiftContainer(i)
		return sc.ObjectsWalk(container, nil, func(opts *swift.ObjectsOpts) (interface{}, error) {
			names, err := sc.ObjectNames(container, opts)
			if err == nil {
				fmt.Println(strings.Join(names, "\n"))
			}
			return names, err
		})
	},
}

func swiftContainer(i *instance.Instance) string {
	if i.SwiftCluster > 0 {
		return "cozy-v2-" + i.DBPrefix()
	}
	return "cozy-" + i.DBPrefix()
}

func init() {
	swiftPutCmd.Flags().StringVar(&flagSwiftObjectContentType, "content-type", "", "Specify a Content-Type for the created object")

	swiftCmdGroup.AddCommand(swiftGetCmd)
	swiftCmdGroup.AddCommand(swiftPutCmd)
	swiftCmdGroup.AddCommand(swiftDeleteCmd)
	swiftCmdGroup.AddCommand(swiftLsCmd)

	RootCmd.AddCommand(swiftCmdGroup)
}
<|endoftext|>


<commit_before>package cmdparser

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

const (
	Standard = 1 << iota
	Preference
	Required
	Hidden
)

var Option map[string]*CmdOption
var Command map[string]*CmdCommand
var Args []string
var Title string
var OptionsFile string
var RequireCommand bool
var SaveOptions func(map[string]interface{}) error

var commandName string
var commandList []CmdCommand
var optionList []CmdOption

func init() {
	Option = make(map[string]*CmdOption)
	Command = make(map[string]*CmdCommand)
	commandName = filepath.Base(os.Args[0])
}

func AddCommand(cmd string, help string, function func()) {
	commandList = append(commandList, CmdCommand{Command: cmd, Help: help, Function: function})
	Command[cmd] = &commandList[len(commandList)-1]
}

func AddOption(name string, cmd string, help string, defaultValue interface{}, flags int) {
	optionList = append(optionList, CmdOption{Name: name, Group: cmd, Help: help, Value: defaultValue, Default: defaultValue, Flags: flags})
	Option[name] = &optionList[len(optionList)-1]
}

func Usage() {
	if Title != "" {
		fmt.Printf(Title + "\n\n")
	}
	fmt.Println("Usage:")
	for _, n := range commandList {
		fmt.Printf("  %s [options] %s %s\n", commandName, n.Command, n.Help)
	}
	fmt.Println("\nOptions:")
	for _, n := range optionList {
		if n.Flags&Hidden == 0 {
			fmt.Printf("  -%s\n        %s", n.Name, n.Help)
			if n.Flags&Preference > 0 {
				fmt.Printf(" (*)")
			}
			if n.DefaultString() != "" {
				fmt.Printf(" (default %s)", n.DefaultString())
			}
			fmt.Print("\n")
		}
	}
	if OptionsFile != "" {
		fmt.Printf("  -save-options\n        Save (*) options to %s\n", OptionsFile)
	}
}

func Parse() error {
	if OptionsFile != "" {
		loadOptions(OptionsFile)
	}

	var stopParsing bool
	var doSave bool
	var doShow bool
	Args = nil
	for i := 0; i < len(os.Args); i++ {
		if !stopParsing && (os.Args[i] == "-?" || os.Args[i] == "-h" || os.Args[i] == "-H") {
			Usage()
			return nil
		} else if !stopParsing && os.Args[i] == "--" {
			stopParsing = true
		} else if !stopParsing && os.Args[i] == "-save-options" {
			doSave = true
		} else if !stopParsing && os.Args[i] == "-show-options" {
			doShow = true
		} else if !stopParsing && os.Args[i][0] == '-' {
			pair := strings.Split(os.Args[i][1:], "=")
			option := Option[pair[0]]
			if option == nil {
				return errors.New("Invalid option -" + pair[0])
			}
			switch option.Value.(type) {
			case bool:
				if len(pair) < 2 && i < len(os.Args)-1 && os.Args[i+1][0] != '-' {
					_, err := strconv.ParseBool(os.Args[i+1])
					if err == nil {
						i++
						pair = append(pair, os.Args[i])
					}
				}
				if len(pair) == 2 {
					b, err := strconv.ParseBool(pair[1])
					if err != nil {
						return errors.New("Invalid value set for option " + pair[0] + ": \"" + pair[1] + "\" is not a boolean")
					}
					option.Value = b
				} else {
					option.Value = true
				}
			default:
				if len(pair) < 2 && i < len(os.Args)-1 && os.Args[i+1][0] != '-' {
					i++
					pair = append(pair, os.Args[i])
				}
				switch option.Value.(type) {
				case bool:
					if len(pair) == 2 {
						b, err := strconv.ParseBool(pair[1])
						if err != nil {
							return errors.New("Invalid value set for option " + pair[0] + ": \"" + pair[1] + "\" is not a boolean")
						}
						option.Value = b
					} else {
						option.Value = true
					}
				case int:
					if len(pair) == 2 {
						i, err := int(strconv.ParseInt(pair[1], 10, 32))
						if err != nil {
							return errors.New("Invalid value set for option " + pair[0] + ": \"" + pair[1] + "\" is not a valid integer")
						}
						option.Value = i
					} else {
						option.Value = option.Default
					}
				case string:
					if len(pair) == 2 {
						option.Value = pair[1]
					} else {
						option.Value = option.Default
					}
				case []string:
					if len(pair) == 2 {
						if option.FromPref {
							option.Value = make([]string, 0)
						}
						option.Value = append(option.Value.([]string), pair[1])
					} else {
						option.Value = option.Default
					}
				default:
					return errors.New("Option value type not supported")
				}
			}
			option.FromPref = false
		} else {
			Args = append(Args, os.Args[i])
		}
	}

	if doSave {
		_, err := saveOptions(OptionsFile)
		if err != nil {
			return err
		}
		fmt.Println("Options saved to " + OptionsFile)
	} else if doShow {
		js, err := jsonOptions()
		if err != nil {
			return err
		}
		fmt.Println(string(js))
	} else {

		if Command[""] == nil {
			if len(Args) < 2 {
				Usage()
				return errors.New("Missing required command")
			} else if Command[Args[1]] == nil {
				return errors.New(Args[1] + " is not a valid command")
			}
		}

		for _, n := range Option {
			if n.Flags&Required > 0 && !n.IsSet() {
				return errors.New("Missing required option -" + n.Name)
			}
		}

		if len(Args) > 1 && Command[Args[1]] != nil && Command[Args[1]].Function != nil {
			Command[Args[1]].Function()
		} else if Command[""] != nil && Command[""].Function != nil {
			Command[""].Function()
		}
	}
	return nil
}

func jsonOptions() ([]byte, error) {
	optionMap := make(map[string]interface{})
	for _, v := range Option {
		if (v.Flags&Preference > 0) && v.String() != v.DefaultString() {
			optionMap[v.Name] = v.Value
		}
	}

	if SaveOptions != nil {
		err := SaveOptions(optionMap)
		if err != nil {
			return nil, err
		}
	}

	jsonData, err := json.MarshalIndent(optionMap, "", "\t")
	if err != nil {
		return nil, err
	}

	return jsonData, nil
}

func saveOptions(name string) (string, error) {
	jsonData, err := jsonOptions()

	err = os.MkdirAll(filepath.Dir(name), 0700)
	if err != nil {
		return "", err
	}
	file, err := os.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0700)
	if err != nil {
		return "", err
	}
	defer file.Close()
	file.Write(jsonData)
	return string(jsonData), nil
}

func loadOptions(name string) error {
	file, err := os.OpenFile(name, os.O_RDONLY, 0700)
	if err != nil {
		return err
	}
	defer file.Close()

	var optionMap map[string]interface{}
	if err := json.NewDecoder(file).Decode(&optionMap); err != nil {
		return err
	}

	for n, v := range optionMap {
		o := Option[n]
		if o != nil {
			switch t := v.(type) {
			case nil: // for JSON null
			// skip
			case map[string]interface{}: // for JSON objects
			// not implemented
			case []interface{}: // for JSON arrays
				o.Value = make([]string, 0)
				for _, s := range t {
					// TODO: add different array types
					o.Value = append(o.Value.([]string), s.(string))
				}
			case string: // for JSON strings
				o.Value = t
			case float64: // for JSON numbers
				o.Value = int(t)
			case bool: // for JSON booleans
				o.Value = t
			}
			o.FromPref = true
		}
	}
	return nil
}

type CmdCommand struct {
	Command  string
	Help     string
	Function func()
	order    int
}

type CmdOption struct {
	Name     string
	Group    string
	Help     string
	Value    interface{}
	Default  interface{}
	FromPref bool
	Flags    int

	order int
}

func (c *CmdOption) Int() int {
	return c.Value.(int)
}
func (c *CmdOption) String() string {
	return fmt.Sprintf("%v", c.Value)
}
func (c *CmdOption) DefaultString() string {
	return fmt.Sprintf("%v", c.Default)
}
func (c *CmdOption) IsSet() bool {
	return c.String() != c.DefaultString()
}
func (c *CmdOption) Set(val interface{}) {
	c.Value = val
	c.FromPref = false
}
<commit_msg>Zzzzz<commit_after>package cmdparser

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

const (
	Standard = 1 << iota
	Preference
	Required
	Hidden
)

var Option map[string]*CmdOption
var Command map[string]*CmdCommand
var Args []string
var Title string
var OptionsFile string
var RequireCommand bool
var SaveOptions func(map[string]interface{}) error

var commandName string
var commandList []CmdCommand
var optionList []CmdOption

func init() {
	Option = make(map[string]*CmdOption)
	Command = make(map[string]*CmdCommand)
	commandName = filepath.Base(os.Args[0])
}

func AddCommand(cmd string, help string, function func()) {
	commandList = append(commandList, CmdCommand{Command: cmd, Help: help, Function: function})
	Command[cmd] = &commandList[len(commandList)-1]
}

func AddOption(name string, cmd string, help string, defaultValue interface{}, flags int) {
	optionList = append(optionList, CmdOption{Name: name, Group: cmd, Help: help, Value: defaultValue, Default: defaultValue, Flags: flags})
	Option[name] = &optionList[len(optionList)-1]
}

func Usage() {
	if Title != "" {
		fmt.Printf(Title + "\n\n")
	}
	fmt.Println("Usage:")
	for _, n := range commandList {
		fmt.Printf("  %s [options] %s %s\n", commandName, n.Command, n.Help)
	}
	fmt.Println("\nOptions:")
	for _, n := range optionList {
		if n.Flags&Hidden == 0 {
			fmt.Printf("  -%s\n        %s", n.Name, n.Help)
			if n.Flags&Preference > 0 {
				fmt.Printf(" (*)")
			}
			if n.DefaultString() != "" {
				fmt.Printf(" (default %s)", n.DefaultString())
			}
			fmt.Print("\n")
		}
	}
	if OptionsFile != "" {
		fmt.Printf("  -save-options\n        Save (*) options to %s\n", OptionsFile)
	}
}

func Parse() error {
	if OptionsFile != "" {
		loadOptions(OptionsFile)
	}

	var stopParsing bool
	var doSave bool
	var doShow bool
	Args = nil
	for i := 0; i < len(os.Args); i++ {
		if !stopParsing && (os.Args[i] == "-?" || os.Args[i] == "-h" || os.Args[i] == "-H") {
			Usage()
			return nil
		} else if !stopParsing && os.Args[i] == "--" {
			stopParsing = true
		} else if !stopParsing && os.Args[i] == "-save-options" {
			doSave = true
		} else if !stopParsing && os.Args[i] == "-show-options" {
			doShow = true
		} else if !stopParsing && os.Args[i][0] == '-' {
			pair := strings.Split(os.Args[i][1:], "=")
			option := Option[pair[0]]
			if option == nil {
				return errors.New("Invalid option -" + pair[0])
			}
			switch option.Value.(type) {
			case bool:
				if len(pair) < 2 && i < len(os.Args)-1 && os.Args[i+1][0] != '-' {
					_, err := strconv.ParseBool(os.Args[i+1])
					if err == nil {
						i++
						pair = append(pair, os.Args[i])
					}
				}
				if len(pair) == 2 {
					b, err := strconv.ParseBool(pair[1])
					if err != nil {
						return errors.New("Invalid value set for option " + pair[0] + ": \"" + pair[1] + "\" is not a boolean")
					}
					option.Value = b
				} else {
					option.Value = true
				}
			default:
				if len(pair) < 2 && i < len(os.Args)-1 && os.Args[i+1][0] != '-' {
					i++
					pair = append(pair, os.Args[i])
				}
				switch option.Value.(type) {
				case bool:
					if len(pair) == 2 {
						b, err := strconv.ParseBool(pair[1])
						if err != nil {
							return errors.New("Invalid value set for option " + pair[0] + ": \"" + pair[1] + "\" is not a boolean")
						}
						option.Value = bool(b)
					} else {
						option.Value = true
					}
				case int:
					if len(pair) == 2 {
						i, err := strconv.ParseInt(pair[1], 10, 32)
						if err != nil {
							return errors.New("Invalid value set for option " + pair[0] + ": \"" + pair[1] + "\" is not a valid integer")
						}
						option.Value = int(i)
					} else {
						option.Value = option.Default
					}
				case string:
					if len(pair) == 2 {
						option.Value = string(pair[1])
					} else {
						option.Value = option.Default.(string)
					}
				case []string:
					if len(pair) == 2 {
						if option.FromPref {
							option.Value = make([]string, 0)
						}
						option.Value = append(option.Value.([]string), pair[1])
					} else {
						option.Value = option.Default
					}
				default:
					return errors.New("Option value type not supported")
				}
			}
			option.FromPref = false
		} else {
			Args = append(Args, os.Args[i])
		}
	}

	if doSave {
		_, err := saveOptions(OptionsFile)
		if err != nil {
			return err
		}
		fmt.Println("Options saved to " + OptionsFile)
	} else if doShow {
		js, err := jsonOptions()
		if err != nil {
			return err
		}
		fmt.Println(string(js))
	} else {

		if Command[""] == nil {
			if len(Args) < 2 {
				Usage()
				return errors.New("Missing required command")
			} else if Command[Args[1]] == nil {
				return errors.New(Args[1] + " is not a valid command")
			}
		}

		for _, n := range Option {
			if n.Flags&Required > 0 && !n.IsSet() {
				return errors.New("Missing required option -" + n.Name)
			}
		}

		if len(Args) > 1 && Command[Args[1]] != nil && Command[Args[1]].Function != nil {
			Command[Args[1]].Function()
		} else if Command[""] != nil && Command[""].Function != nil {
			Command[""].Function()
		}
	}
	return nil
}

func jsonOptions() ([]byte, error) {
	optionMap := make(map[string]interface{})
	for _, v := range Option {
		if (v.Flags&Preference > 0) && v.String() != v.DefaultString() {
			optionMap[v.Name] = v.Value
		}
	}

	if SaveOptions != nil {
		err := SaveOptions(optionMap)
		if err != nil {
			return nil, err
		}
	}

	jsonData, err := json.MarshalIndent(optionMap, "", "\t")
	if err != nil {
		return nil, err
	}

	return jsonData, nil
}

func saveOptions(name string) (string, error) {
	jsonData, err := jsonOptions()

	err = os.MkdirAll(filepath.Dir(name), 0700)
	if err != nil {
		return "", err
	}
	file, err := os.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0700)
	if err != nil {
		return "", err
	}
	defer file.Close()
	file.Write(jsonData)
	return string(jsonData), nil
}

func loadOptions(name string) error {
	file, err := os.OpenFile(name, os.O_RDONLY, 0700)
	if err != nil {
		return err
	}
	defer file.Close()

	var optionMap map[string]interface{}
	if err := json.NewDecoder(file).Decode(&optionMap); err != nil {
		return err
	}

	for n, v := range optionMap {
		o := Option[n]
		if o != nil {
			switch t := v.(type) {
			case nil: // for JSON null
			// skip
			case map[string]interface{}: // for JSON objects
			// not implemented
			case []interface{}: // for JSON arrays
				o.Value = make([]string, 0)
				for _, s := range t {
					// TODO: add different array types
					o.Value = append(o.Value.([]string), s.(string))
				}
			case string: // for JSON strings
				o.Value = t
			case float64: // for JSON numbers
				o.Value = int(t)
			case bool: // for JSON booleans
				o.Value = t
			}
			o.FromPref = true
		}
	}
	return nil
}

type CmdCommand struct {
	Command  string
	Help     string
	Function func()
	order    int
}

type CmdOption struct {
	Name     string
	Group    string
	Help     string
	Value    interface{}
	Default  interface{}
	FromPref bool
	Flags    int

	order int
}

func (c *CmdOption) Int() int {
	return c.Value.(int)
}
func (c *CmdOption) String() string {
	return fmt.Sprintf("%v", c.Value)
}
func (c *CmdOption) DefaultString() string {
	return fmt.Sprintf("%v", c.Default)
}
func (c *CmdOption) IsSet() bool {
	return c.String() != c.DefaultString()
}
func (c *CmdOption) Set(val interface{}) {
	c.Value = val
	c.FromPref = false
}
<|endoftext|>


<commit_before>package common

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/signal"
	"strings"
)

var (
	GoPath = os.Getenv("GOPATH")
)

func TrapSignal(cb func()) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, os.Kill)
	go func() {
		for sig := range c {
			fmt.Printf("captured %v, exiting...\n", sig)
			if cb != nil {
				cb()
			}
			os.Exit(1)
		}
	}()
	select {}
}

func Exit(s string) {
	fmt.Printf(s + "\n")
	os.Exit(1)
}

func EnsureDir(dir string, mode os.FileMode) error {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err := os.MkdirAll(dir, mode)
		if err != nil {
			return fmt.Errorf("Could not create directory %v. %v", dir, err)
		}
	}
	return nil
}

func IsDirEmpty(name string) (bool, error) {
	f, err := os.Open(name)
	if err != nil {
		return true, err //folder is non-existent
	}
	defer f.Close()

	_, err = f.Readdirnames(1) // Or f.Readdir(1)
	if err == io.EOF {
		return true, nil
	}
	return false, err // Either not empty or error, suits both cases
}

func FileExists(filePath string) bool {
	_, err := os.Stat(filePath)
	return !os.IsNotExist(err)
}

func ReadFile(filePath string) ([]byte, error) {
	return ioutil.ReadFile(filePath)
}

func MustReadFile(filePath string) []byte {
	fileBytes, err := ioutil.ReadFile(filePath)
	if err != nil {
		Exit(Fmt("MustReadFile failed: %v", err))
		return nil
	}
	return fileBytes
}

func WriteFile(filePath string, contents []byte, mode os.FileMode) error {
	err := ioutil.WriteFile(filePath, contents, mode)
	if err != nil {
		return err
	}
	// fmt.Printf("File written to %v.\n", filePath)
	return nil
}

func MustWriteFile(filePath string, contents []byte, mode os.FileMode) {
	err := WriteFile(filePath, contents, mode)
	if err != nil {
		Exit(Fmt("MustWriteFile failed: %v", err))
	}
}

// Writes to newBytes to filePath.
// Guaranteed not to lose *both* oldBytes and newBytes,
// (assuming that the OS is perfect)
func WriteFileAtomic(filePath string, newBytes []byte, mode os.FileMode) error {
	// If a file already exists there, copy to filePath+".bak" (overwrite anything)
	if _, err := os.Stat(filePath); !os.IsNotExist(err) {
		fileBytes, err := ioutil.ReadFile(filePath)
		if err != nil {
			return fmt.Errorf("Could not read file %v. %v", filePath, err)
		}
		err = ioutil.WriteFile(filePath+".bak", fileBytes, mode)
		if err != nil {
			return fmt.Errorf("Could not write file %v. %v", filePath+".bak", err)
		}
	}
	// Write newBytes to filePath.new
	err := ioutil.WriteFile(filePath+".new", newBytes, mode)
	if err != nil {
		return fmt.Errorf("Could not write file %v. %v", filePath+".new", err)
	}
	// Move filePath.new to filePath
	err = os.Rename(filePath+".new", filePath)
	return err
}

//--------------------------------------------------------------------------------

func Tempfile(prefix string) (*os.File, string) {
	file, err := ioutil.TempFile("", prefix)
	if err != nil {
		PanicCrisis(err)
	}
	return file, file.Name()
}

func Tempdir(prefix string) (*os.File, string) {
	tempDir := os.TempDir() + "/" + prefix + RandStr(12)
	err := EnsureDir(tempDir, 0700)
	if err != nil {
		panic(Fmt("Error creating temp dir: %v", err))
	}
	dir, err := os.Open(tempDir)
	if err != nil {
		panic(Fmt("Error opening temp dir: %v", err))
	}
	return dir, tempDir
}

//--------------------------------------------------------------------------------

func Prompt(prompt string, defaultValue string) (string, error) {
	fmt.Print(prompt)
	reader := bufio.NewReader(os.Stdin)
	line, err := reader.ReadString('\n')
	if err != nil {
		return defaultValue, err
	} else {
		line = strings.TrimSpace(line)
		if line == "" {
			return defaultValue, nil
		}
		return line, nil
	}
}
<commit_msg>common/IsDirEmpty: do not mask non-existance errors<commit_after>package common

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/signal"
	"strings"
)

var (
	GoPath = os.Getenv("GOPATH")
)

func TrapSignal(cb func()) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, os.Kill)
	go func() {
		for sig := range c {
			fmt.Printf("captured %v, exiting...\n", sig)
			if cb != nil {
				cb()
			}
			os.Exit(1)
		}
	}()
	select {}
}

func Exit(s string) {
	fmt.Printf(s + "\n")
	os.Exit(1)
}

func EnsureDir(dir string, mode os.FileMode) error {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err := os.MkdirAll(dir, mode)
		if err != nil {
			return fmt.Errorf("Could not create directory %v. %v", dir, err)
		}
	}
	return nil
}

func IsDirEmpty(name string) (bool, error) {
	f, err := os.Open(name)
	if err != nil {
		if os.IsNotExist(err) {
			return true, err
		}
		// Otherwise perhaps a permission
		// error or some other error.
		return false, err
	}
	defer f.Close()

	_, err = f.Readdirnames(1) // Or f.Readdir(1)
	if err == io.EOF {
		return true, nil
	}
	return false, err // Either not empty or error, suits both cases
}

func FileExists(filePath string) bool {
	_, err := os.Stat(filePath)
	return !os.IsNotExist(err)
}

func ReadFile(filePath string) ([]byte, error) {
	return ioutil.ReadFile(filePath)
}

func MustReadFile(filePath string) []byte {
	fileBytes, err := ioutil.ReadFile(filePath)
	if err != nil {
		Exit(Fmt("MustReadFile failed: %v", err))
		return nil
	}
	return fileBytes
}

func WriteFile(filePath string, contents []byte, mode os.FileMode) error {
	err := ioutil.WriteFile(filePath, contents, mode)
	if err != nil {
		return err
	}
	// fmt.Printf("File written to %v.\n", filePath)
	return nil
}

func MustWriteFile(filePath string, contents []byte, mode os.FileMode) {
	err := WriteFile(filePath, contents, mode)
	if err != nil {
		Exit(Fmt("MustWriteFile failed: %v", err))
	}
}

// Writes to newBytes to filePath.
// Guaranteed not to lose *both* oldBytes and newBytes,
// (assuming that the OS is perfect)
func WriteFileAtomic(filePath string, newBytes []byte, mode os.FileMode) error {
	// If a file already exists there, copy to filePath+".bak" (overwrite anything)
	if _, err := os.Stat(filePath); !os.IsNotExist(err) {
		fileBytes, err := ioutil.ReadFile(filePath)
		if err != nil {
			return fmt.Errorf("Could not read file %v. %v", filePath, err)
		}
		err = ioutil.WriteFile(filePath+".bak", fileBytes, mode)
		if err != nil {
			return fmt.Errorf("Could not write file %v. %v", filePath+".bak", err)
		}
	}
	// Write newBytes to filePath.new
	err := ioutil.WriteFile(filePath+".new", newBytes, mode)
	if err != nil {
		return fmt.Errorf("Could not write file %v. %v", filePath+".new", err)
	}
	// Move filePath.new to filePath
	err = os.Rename(filePath+".new", filePath)
	return err
}

//--------------------------------------------------------------------------------

func Tempfile(prefix string) (*os.File, string) {
	file, err := ioutil.TempFile("", prefix)
	if err != nil {
		PanicCrisis(err)
	}
	return file, file.Name()
}

func Tempdir(prefix string) (*os.File, string) {
	tempDir := os.TempDir() + "/" + prefix + RandStr(12)
	err := EnsureDir(tempDir, 0700)
	if err != nil {
		panic(Fmt("Error creating temp dir: %v", err))
	}
	dir, err := os.Open(tempDir)
	if err != nil {
		panic(Fmt("Error opening temp dir: %v", err))
	}
	return dir, tempDir
}

//--------------------------------------------------------------------------------

func Prompt(prompt string, defaultValue string) (string, error) {
	fmt.Print(prompt)
	reader := bufio.NewReader(os.Stdin)
	line, err := reader.ReadString('\n')
	if err != nil {
		return defaultValue, err
	} else {
		line = strings.TrimSpace(line)
		if line == "" {
			return defaultValue, nil
		}
		return line, nil
	}
}
<|endoftext|>


<commit_before>package mithril

// Component for Mithril
type Component interface {
	Controller()
	View() interface{}
}

// ExtendComponent creates a basic component view
func ExtendComponent() *BaseComponent {
	return &BaseComponent{make(map[string]interface{})}
}

// BaseComponent contains a controller and a view properties.
type BaseComponent struct {
	scope map[string]interface{}
}

// Controller function creates map for View
func (component *BaseComponent) Controller() {
	panic("please override Controller function")
}

// View function creates VirtualElement or string, int, bool
func (component *BaseComponent) View() interface{} {
	panic("please override View function")
	return nil
}

// Get returns controller value
func (component *BaseComponent) Get(key string) interface{} {
	return component.scope[key]
}

// Set value to controller scope
func (component *BaseComponent) Set(key string, val interface{}) {
	component.scope[key] = val
}
<commit_msg>update Component Get Set<commit_after>package mithril

// Component for Mithril
type Component interface {
	Controller()
	View() interface{}
	Get(string) interface{}
	Set(string, interface{})
}

// ExtendComponent creates a basic component view
func ExtendComponent() *BaseComponent {
	return &BaseComponent{make(map[string]interface{})}
}

// BaseComponent contains a controller and a view properties.
type BaseComponent struct {
	scope map[string]interface{}
}

// Controller function creates map for View
func (component *BaseComponent) Controller() {
	panic("please override Controller function")
}

// View function creates VirtualElement or string, int, bool
func (component *BaseComponent) View() interface{} {
	panic("please override View function")
	return nil
}

// Get returns controller value
func (component *BaseComponent) Get(key string) interface{} {
	return component.scope[key]
}

// Set value to controller scope
func (component *BaseComponent) Set(key string, val interface{}) {
	component.scope[key] = val
}
<|endoftext|>


<commit_before>package boardgame

import (
	"crypto/sha1"
	"fmt"
	"strconv"
)

//A Component represents a movable resource in the game. Cards, dice, meeples,
//resource tokens, etc are all components. Values is a struct that stores the
//specific values for the component.
type Component struct {
	Values SubState
	//The deck we're a part of.
	Deck *Deck
	//The index we are in the deck we're in.
	DeckIndex int
}

//Id returns a semi-stable ID for this component within this game and
//currentState. Within this game, it will only change when the shuffleCount
//for this component changes. Across games the Id for the "same" component
//will be different, in a way that cannot be guessed without access to
//game.SecretSalt. See the package doc for more on semi-stable Ids for
//components, what they can be used for, and when they do (and don't) change.
func (c *Component) Id(s State) string {

	//Shadow components shouldn't get an Id
	if c == c.Deck.GenericComponent() {
		return ""
	}

	//S should  never be nil in normal circumstances, but if it is, return an
	//obviously-special Id so it doesn't appear to be the actual Id for this
	//component.
	if s == nil {
		return ""
	}

	st := s.(*state)

	input := "insecuredefaultinput"

	//This is only nil in very weird, testing use cases, like
	//blackjack.handvalue.
	if st != nil {
		game := st.game
		input = game.Id() + game.SecretSalt()
	}

	input += c.Deck.Name() + strconv.Itoa(c.DeckIndex)

	//The id only ever changes when the item has moved secretly.
	input += strconv.Itoa(c.secretMoveCount(st))

	hash := sha1.Sum([]byte(input))

	return fmt.Sprintf("%x", hash)
}

//secretMoveCount returns the secret move count for this component in the
//given state.
func (c *Component) secretMoveCount(s *state) int {

	if c == c.Deck.GenericComponent() {
		return 0
	}

	if s == nil {
		return 0
	}

	deckMoveCount, ok := s.secretMoveCount[c.Deck.Name()]

	//No components in that deck have been moved secretly, I guess.
	if !ok {
		return 0
	}

	if c.DeckIndex >= len(deckMoveCount) {
		//TODO: warn?
		return 0
	}

	if c.DeckIndex < 0 {
		//This should never happen
		return 0
	}

	return deckMoveCount[c.DeckIndex]
}

//movedSecretly increments the secretMoveCount for this component.
func (c *Component) movedSecretly(s *state) {
	if c == c.Deck.GenericComponent() {
		return
	}

	if s == nil {
		return
	}

	deckMoveCount, ok := s.secretMoveCount[c.Deck.Name()]

	//We must be the first component in this deck that has been secretly
	//moved. Create the whole int stack for this group.
	if !ok {
		//The zero-value will be fine
		deckMoveCount = make([]int, len(c.Deck.Components()))
		s.secretMoveCount[c.Deck.Name()] = deckMoveCount
	}

	if c.DeckIndex >= len(deckMoveCount) {
		//TODO: warn?
		return
	}

	if c.DeckIndex < 0 {
		//This should never happen
		return
	}

	deckMoveCount[c.DeckIndex]++

}

func (c *Component) DynamicValues(state State) SubState {

	//TODO: test this

	dynamic := state.DynamicComponentValues()

	values := dynamic[c.Deck.Name()]

	if values == nil {
		return nil
	}

	if len(values) <= c.DeckIndex {
		return nil
	}

	if c.DeckIndex < 0 {
		//TODO: is this the right beahvior now that we have auto-inflation?
		return c.Deck.Chest().Manager().Delegate().DynamicComponentValuesConstructor(c.Deck)
	}

	return values[c.DeckIndex]
}
<commit_msg>Now Components have a Reader too. Part of #502.<commit_after>package boardgame

import (
	"crypto/sha1"
	"fmt"
	"strconv"
)

//A Component represents a movable resource in the game. Cards, dice, meeples,
//resource tokens, etc are all components. Values is a struct that stores the
//specific values for the component.
type Component struct {
	Values Reader
	//The deck we're a part of.
	Deck *Deck
	//The index we are in the deck we're in.
	DeckIndex int
}

//Id returns a semi-stable ID for this component within this game and
//currentState. Within this game, it will only change when the shuffleCount
//for this component changes. Across games the Id for the "same" component
//will be different, in a way that cannot be guessed without access to
//game.SecretSalt. See the package doc for more on semi-stable Ids for
//components, what they can be used for, and when they do (and don't) change.
func (c *Component) Id(s State) string {

	//Shadow components shouldn't get an Id
	if c == c.Deck.GenericComponent() {
		return ""
	}

	//S should  never be nil in normal circumstances, but if it is, return an
	//obviously-special Id so it doesn't appear to be the actual Id for this
	//component.
	if s == nil {
		return ""
	}

	st := s.(*state)

	input := "insecuredefaultinput"

	//This is only nil in very weird, testing use cases, like
	//blackjack.handvalue.
	if st != nil {
		game := st.game
		input = game.Id() + game.SecretSalt()
	}

	input += c.Deck.Name() + strconv.Itoa(c.DeckIndex)

	//The id only ever changes when the item has moved secretly.
	input += strconv.Itoa(c.secretMoveCount(st))

	hash := sha1.Sum([]byte(input))

	return fmt.Sprintf("%x", hash)
}

//secretMoveCount returns the secret move count for this component in the
//given state.
func (c *Component) secretMoveCount(s *state) int {

	if c == c.Deck.GenericComponent() {
		return 0
	}

	if s == nil {
		return 0
	}

	deckMoveCount, ok := s.secretMoveCount[c.Deck.Name()]

	//No components in that deck have been moved secretly, I guess.
	if !ok {
		return 0
	}

	if c.DeckIndex >= len(deckMoveCount) {
		//TODO: warn?
		return 0
	}

	if c.DeckIndex < 0 {
		//This should never happen
		return 0
	}

	return deckMoveCount[c.DeckIndex]
}

//movedSecretly increments the secretMoveCount for this component.
func (c *Component) movedSecretly(s *state) {
	if c == c.Deck.GenericComponent() {
		return
	}

	if s == nil {
		return
	}

	deckMoveCount, ok := s.secretMoveCount[c.Deck.Name()]

	//We must be the first component in this deck that has been secretly
	//moved. Create the whole int stack for this group.
	if !ok {
		//The zero-value will be fine
		deckMoveCount = make([]int, len(c.Deck.Components()))
		s.secretMoveCount[c.Deck.Name()] = deckMoveCount
	}

	if c.DeckIndex >= len(deckMoveCount) {
		//TODO: warn?
		return
	}

	if c.DeckIndex < 0 {
		//This should never happen
		return
	}

	deckMoveCount[c.DeckIndex]++

}

func (c *Component) DynamicValues(state State) SubState {

	//TODO: test this

	dynamic := state.DynamicComponentValues()

	values := dynamic[c.Deck.Name()]

	if values == nil {
		return nil
	}

	if len(values) <= c.DeckIndex {
		return nil
	}

	if c.DeckIndex < 0 {
		//TODO: is this the right beahvior now that we have auto-inflation?
		return c.Deck.Chest().Manager().Delegate().DynamicComponentValuesConstructor(c.Deck)
	}

	return values[c.DeckIndex]
}
<|endoftext|>


<commit_before>package conf

import (
	"encoding/json"
	"fmt"
	"os"
	"path"
)

type config struct {
	// serving options
	ProjectRoot string
	Debug       bool

	WebHost    string "web address"
	WebPort    int    "web port"
	HttpPrefix string

	SessionSecret             string
	GoogleAnalyticsTrackingID string

	StaticPath         string
	TemplatePaths      []string
	TemplatePreCompile bool

	DbHost string
	DbPort int
	DbName string

	Gallery map[string]string
}

var Path = "./config.json"
var Config = new(config)

func (c *config) HostString() string {
	return fmt.Sprintf("%s:%d", c.WebHost, c.WebPort)
}

func (c *config) DbHostString() string {
	if c.DbPort > 0 {
		return fmt.Sprintf("mongodb://%s:%d", c.DbHost, c.DbPort)
	}
	return fmt.Sprintf("mongodb://%s", c.DbHost)
}

func (c *config) String() string {
	s := "Config:"
	s += fmt.Sprintf("   Host: %s,\n", c.HostString())
	s += fmt.Sprintf("   HttpPrefix: %s,\n", c.HttpPrefix)
	s += fmt.Sprintf("   DB: %s,\n", c.DbHostString())
	s += fmt.Sprintf("   TemplatePaths: %s,\n", c.TemplatePaths)
	s += fmt.Sprintf("   StaticPath: %s,\n", c.StaticPath)
	s += fmt.Sprintf("   TemplatePreCompile: %v,\n", c.TemplatePreCompile)
	s += fmt.Sprintf("   Debug: %v\n", c.Debug)
	s += fmt.Sprintf("   Gallery: %v\n", c.Gallery)
	s += fmt.Sprintf("   GoogleAnalyticsTrackingID: %v\n", c.GoogleAnalyticsTrackingID)
	return s
}

func (c *config) AddTemplatePath(path string) {
	c.TemplatePaths = append(c.TemplatePaths, path)
}

func init() {
	// defaults
	Config.WebHost = "0.0.0.0"
	Config.WebPort = 5050
	Config.HttpPrefix = "/"
	Config.DbHost = "127.0.0.1"
	Config.DbPort = 0
	Config.DbName = "the_db"
	Config.StaticPath = "./static"
	Config.AddTemplatePath("./templates")
	Config.SessionSecret = "SECRET-KEY-SET-IN-CONFIG"
	Config.Debug = false
	Config.TemplatePreCompile = true

	if ecp := os.Getenv("PROJ_CONFIG_PATH"); ecp != "" {
		Path = path.Join(ecp, "config.json")
		Config.ProjectRoot = ecp
	}

	file, err := os.Open(Path)
	if err != nil {
		if len(Path) > 1 {
			fmt.Printf("Error: could not read config file %s.\n", Path)
		}
		return
	}
	decoder := json.NewDecoder(file)
	// overwrite in-mem config with new values
	err = decoder.Decode(Config)
	if err != nil {
		fmt.Printf("Error decoding file %s\n%s\n", Path, err)
	}
}
<commit_msg>Set project root to be relative to the executable.<commit_after>package conf

import (
	"encoding/json"
	"fmt"
	"os"
	"path"

	"bitbucket.org/kardianos/osext"
)

type config struct {
	// serving options
	ProjectRoot string
	Debug       bool

	WebHost    string "web address"
	WebPort    int    "web port"
	HttpPrefix string

	SessionSecret             string
	GoogleAnalyticsTrackingID string

	StaticPath         string
	TemplatePaths      []string
	TemplatePreCompile bool

	DbHost string
	DbPort int
	DbName string

	Gallery map[string]string
}

var Path = "./config.json"
var Config = new(config)

func (c *config) HostString() string {
	return fmt.Sprintf("%s:%d", c.WebHost, c.WebPort)
}

func (c *config) DbHostString() string {
	if c.DbPort > 0 {
		return fmt.Sprintf("mongodb://%s:%d", c.DbHost, c.DbPort)
	}
	return fmt.Sprintf("mongodb://%s", c.DbHost)
}

func (c *config) String() string {
	s := "Config:"
	s += fmt.Sprintf("   Host: %s,\n", c.HostString())
	s += fmt.Sprintf("   HttpPrefix: %s,\n", c.HttpPrefix)
	s += fmt.Sprintf("   DB: %s,\n", c.DbHostString())
	s += fmt.Sprintf("   TemplatePaths: %s,\n", c.TemplatePaths)
	s += fmt.Sprintf("   StaticPath: %s,\n", c.StaticPath)
	s += fmt.Sprintf("   TemplatePreCompile: %v,\n", c.TemplatePreCompile)
	s += fmt.Sprintf("   Debug: %v\n", c.Debug)
	s += fmt.Sprintf("   Gallery: %v\n", c.Gallery)
	s += fmt.Sprintf("   GoogleAnalyticsTrackingID: %v\n", c.GoogleAnalyticsTrackingID)
	return s
}

func (c *config) AddTemplatePath(path string) {
	c.TemplatePaths = append(c.TemplatePaths, path)
}

func init() {
	// defaults
	Config.WebHost = "0.0.0.0"
	Config.WebPort = 5050
	Config.HttpPrefix = "/"
	Config.DbHost = "127.0.0.1"
	Config.DbPort = 0
	Config.DbName = "the_db"
	Config.StaticPath = "./static"
	Config.AddTemplatePath("./templates")
	Config.SessionSecret = "SECRET-KEY-SET-IN-CONFIG"
	Config.Debug = false
	Config.TemplatePreCompile = true

	exename, _ := osext.Executable()
	projRoot := path.Dir(exename)

	Path = path.Join(projRoot, "config.json")
	Config.ProjectRoot = projRoot

	file, err := os.Open(Path)
	if err != nil {
		if len(Path) > 1 {
			fmt.Printf("Error: could not read config file %s.\n", Path)
		}
		return
	}
	decoder := json.NewDecoder(file)
	// overwrite in-mem config with new values
	err = decoder.Decode(Config)
	if err != nil {
		fmt.Printf("Error decoding file %s\n%s\n", Path, err)
	}
}
<|endoftext|>


<commit_before>package invoicegenerator

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
)

const requestURL = "https://invoice-generator.com"
const requestType = "application/json"

type Invoice struct {
	Header             string `json:"header,omitempty"`
	ToTitle            string `json:"to_title,omitempty"`
	InvoiceNumberTitle string `json:"invoice_number_title,omitempty"`
	DateTitle          string `json:"date_title,omitempty"`
	PaymentTermsTitle  string `json:"payment_terms_title,omitempty"`
	DueDateTitle       string `json:"due_date_title,omitempty"`
	PurchaseOrderTitle string `json:"purchase_order_title,omitempty"`
	QuantityHeader     string `json:"quantity_header,omitempty"`
	ItemHeader         string `json:"item_header,omitempty"`
	UnitCostHeader     string `json:"unit_cost_header,omitempty"`
	AmountHeader       string `json:"amount_header,omitempty"`
	SubtotalTitle      string `json:"subtotal_title,omitempty"`
	DiscountsTitle     string `json:"discounts_title,omitempty"`
	TaxTitle           string `json:"tax_title,omitempty"`
	ShippingTitle      string `json:"shipping_title,omitempty"`
	TotalTitle         string `json:"total_title,omitempty"`
	AmountPaidTitle    string `json:"amount_paid_title,omitempty"`
	BalanceTitle       string `json:"balance_title,omitempty"`
	TermsTitle         string `json:"terms_title,omitempty"`
	NotesTitle         string `json:"notes_title,omitempty"`

	Currency string `json:"currency,omitempty"`

	From          string  `json:"from"`
	To            string  `json:"to"`
	Logo          string  `json:"logo,omitempty"`
	Number        string  `json:"number,omitempty"`
	PurchaseOrder string  `json:"purchase_order,omitempty"`
	Date          string  `json:"date"`
	PaymentTerms  string  `json:"payment_terms,omitempty"`
	Items         []Item  `json:"items"`
	Fields        Field   `json:"field,omitempty"`
	Discounts     float64 `json:"discounts,omitempty"`
	Tax           float64 `json:"tax,omitempty"`
	Shipping      float64 `json:"shipping,omitempty"`
	AmountPaid    float64 `json:"amount_paid,omitempty"`
	Notes         string  `json:"notes,omitempty"`
	Terms         string  `json:"terms,omitempty"`
}

type Item struct {
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Quantity    int64   `json:"quantity"`
	Unit_cost   float64 `json:"unit_cost"`
}

type Field struct {
	Tax       string  `json:"tax"`
	Discounts float64 `json:"discounts"`
	Shipping  float64 `json:"shipping"`
}

func (i *Invoice) Create(filename string, fileDir string) {
	b, err := json.Marshal(*i)
	if err != nil {
		panic(err)
	}

	client := &http.Client{}

	resp, err := client.Post(requestURL, requestType, bytes.NewBuffer(b))
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

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

	if err != nil {
		panic(err)
	}

	f := fileDir + filename + ".pdf"

	err = ioutil.WriteFile(f, body, 0644)

	if err != nil {
		panic(err)
	}

}
<commit_msg>Make `Quantity` float64, swap panic for `return err`, use full file path<commit_after>package invoicegenerator

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net/http"
)

const requestURL = "https://invoice-generator.com"
const requestType = "application/json"

type Invoice struct {
	Header             string `json:"header,omitempty"`
	ToTitle            string `json:"to_title,omitempty"`
	InvoiceNumberTitle string `json:"invoice_number_title,omitempty"`
	DateTitle          string `json:"date_title,omitempty"`
	PaymentTermsTitle  string `json:"payment_terms_title,omitempty"`
	DueDateTitle       string `json:"due_date_title,omitempty"`
	PurchaseOrderTitle string `json:"purchase_order_title,omitempty"`
	QuantityHeader     string `json:"quantity_header,omitempty"`
	ItemHeader         string `json:"item_header,omitempty"`
	UnitCostHeader     string `json:"unit_cost_header,omitempty"`
	AmountHeader       string `json:"amount_header,omitempty"`
	SubtotalTitle      string `json:"subtotal_title,omitempty"`
	DiscountsTitle     string `json:"discounts_title,omitempty"`
	TaxTitle           string `json:"tax_title,omitempty"`
	ShippingTitle      string `json:"shipping_title,omitempty"`
	TotalTitle         string `json:"total_title,omitempty"`
	AmountPaidTitle    string `json:"amount_paid_title,omitempty"`
	BalanceTitle       string `json:"balance_title,omitempty"`
	TermsTitle         string `json:"terms_title,omitempty"`
	NotesTitle         string `json:"notes_title,omitempty"`

	Currency string `json:"currency,omitempty"`

	From          string  `json:"from"`
	To            string  `json:"to"`
	Logo          string  `json:"logo,omitempty"`
	Number        string  `json:"number,omitempty"`
	PurchaseOrder string  `json:"purchase_order,omitempty"`
	Date          string  `json:"date"`
	PaymentTerms  string  `json:"payment_terms,omitempty"`
	Items         []Item  `json:"items"`
	Fields        Field   `json:"field,omitempty"`
	Discounts     float64 `json:"discounts,omitempty"`
	Tax           float64 `json:"tax,omitempty"`
	Shipping      float64 `json:"shipping,omitempty"`
	AmountPaid    float64 `json:"amount_paid,omitempty"`
	Notes         string  `json:"notes,omitempty"`
	Terms         string  `json:"terms,omitempty"`
}

type Item struct {
	Name        string  `json:"name"`
	Description string  `json:"description"`
	Quantity    float64 `json:"quantity"`
	Unit_cost   float64 `json:"unit_cost"`
}

type Field struct {
	Tax       string  `json:"tax"`
	Discounts float64 `json:"discounts"`
	Shipping  float64 `json:"shipping"`
}

func (i *Invoice) Create(fullFilePath string) error {
	b, err := json.Marshal(*i)
	if err != nil {
		return err
	}

	client := &http.Client{}

	resp, err := client.Post(requestURL, requestType, bytes.NewBuffer(b))
	if err != nil {
		return err
	}
	defer resp.Body.Close()

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

	if err != nil {
		return err
	}

	err = ioutil.WriteFile(fullFilePath, body, 0644)

	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2019, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package awsxrayexporter

import (
	"context"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/xray"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/config/configmodels"
	"go.opentelemetry.io/collector/consumer/consumererror"
	"go.opentelemetry.io/collector/consumer/pdata"
	"go.opentelemetry.io/collector/exporter/exporterhelper"
	"go.uber.org/zap"

	"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter/translator"
)

const (
	maxSegmentsPerPut = int(50) // limit imposed by PutTraceSegments API
)

// newTraceExporter creates an component.TraceExporter that converts to an X-Ray PutTraceSegments
// request and then posts the request to the configured region's X-Ray endpoint.
func newTraceExporter(
	config configmodels.Exporter, params component.ExporterCreateParams, cn connAttr) (component.TracesExporter, error) {
	typeLog := zap.String("type", string(config.Type()))
	nameLog := zap.String("name", config.Name())
	logger := params.Logger
	awsConfig, session, err := GetAWSConfigSession(logger, cn, config.(*Config))
	if err != nil {
		return nil, err
	}
	xrayClient := newXRay(logger, awsConfig, params.ApplicationStartInfo, session)
	return exporterhelper.NewTraceExporter(
		config,
		logger,
		func(ctx context.Context, td pdata.Traces) (totalDroppedSpans int, err error) {
			logger.Debug("TraceExporter", typeLog, nameLog, zap.Int("#spans", td.SpanCount()))
			totalDroppedSpans = 0
			documents := make([]*string, 0, td.SpanCount())
			for i := 0; i < td.ResourceSpans().Len(); i++ {
				rspans := td.ResourceSpans().At(i)
				resource := rspans.Resource()
				for j := 0; j < rspans.InstrumentationLibrarySpans().Len(); j++ {
					spans := rspans.InstrumentationLibrarySpans().At(j).Spans()
					for k := 0; k < spans.Len(); k++ {
						document, localErr := translator.MakeSegmentDocumentString(spans.At(k), resource,
							config.(*Config).IndexedAttributes, config.(*Config).IndexAllAttributes)
						if localErr != nil {
							totalDroppedSpans++
							continue
						}
						documents = append(documents, &document)
					}
				}
			}
			for offset := 0; offset < len(documents); offset += maxSegmentsPerPut {
				nextOffset := offset + maxSegmentsPerPut
				if nextOffset > td.SpanCount() {
					nextOffset = td.SpanCount()
				}
				input := xray.PutTraceSegmentsInput{TraceSegmentDocuments: documents[offset:nextOffset]}
				logger.Debug("request: " + input.String())
				output, localErr := xrayClient.PutTraceSegments(&input)
				if localErr != nil {
					logger.Debug("response error", zap.Error(localErr))
					err = wrapErrorIfBadRequest(&localErr) // record error
				}
				if output != nil {
					logger.Debug("response: " + output.String())
					if output.UnprocessedTraceSegments != nil {
						totalDroppedSpans += len(output.UnprocessedTraceSegments)
					}
				}
				if err != nil {
					break
				}
			}
			return totalDroppedSpans, err
		},
		exporterhelper.WithShutdown(func(context.Context) error {
			return logger.Sync()
		}),
	)
}

func wrapErrorIfBadRequest(err *error) error {
	_, ok := (*err).(awserr.RequestFailure)
	if ok && (*err).(awserr.RequestFailure).StatusCode() < 500 {
		return consumererror.Permanent(*err)
	}
	return *err
}
<commit_msg>Log error when translating span. (#1809)<commit_after>// Copyright 2019, OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package awsxrayexporter

import (
	"context"

	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/xray"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/config/configmodels"
	"go.opentelemetry.io/collector/consumer/consumererror"
	"go.opentelemetry.io/collector/consumer/pdata"
	"go.opentelemetry.io/collector/exporter/exporterhelper"
	"go.uber.org/zap"

	"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/awsxrayexporter/translator"
)

const (
	maxSegmentsPerPut = int(50) // limit imposed by PutTraceSegments API
)

// newTraceExporter creates an component.TraceExporter that converts to an X-Ray PutTraceSegments
// request and then posts the request to the configured region's X-Ray endpoint.
func newTraceExporter(
	config configmodels.Exporter, params component.ExporterCreateParams, cn connAttr) (component.TracesExporter, error) {
	typeLog := zap.String("type", string(config.Type()))
	nameLog := zap.String("name", config.Name())
	logger := params.Logger
	awsConfig, session, err := GetAWSConfigSession(logger, cn, config.(*Config))
	if err != nil {
		return nil, err
	}
	xrayClient := newXRay(logger, awsConfig, params.ApplicationStartInfo, session)
	return exporterhelper.NewTraceExporter(
		config,
		logger,
		func(ctx context.Context, td pdata.Traces) (totalDroppedSpans int, err error) {
			logger.Debug("TraceExporter", typeLog, nameLog, zap.Int("#spans", td.SpanCount()))
			totalDroppedSpans = 0
			documents := make([]*string, 0, td.SpanCount())
			for i := 0; i < td.ResourceSpans().Len(); i++ {
				rspans := td.ResourceSpans().At(i)
				resource := rspans.Resource()
				for j := 0; j < rspans.InstrumentationLibrarySpans().Len(); j++ {
					spans := rspans.InstrumentationLibrarySpans().At(j).Spans()
					for k := 0; k < spans.Len(); k++ {
						document, localErr := translator.MakeSegmentDocumentString(spans.At(k), resource,
							config.(*Config).IndexedAttributes, config.(*Config).IndexAllAttributes)
						if localErr != nil {
							logger.Debug("Error translating span.", zap.Error(localErr))
							totalDroppedSpans++
							continue
						}
						documents = append(documents, &document)
					}
				}
			}
			for offset := 0; offset < len(documents); offset += maxSegmentsPerPut {
				nextOffset := offset + maxSegmentsPerPut
				if nextOffset > td.SpanCount() {
					nextOffset = td.SpanCount()
				}
				input := xray.PutTraceSegmentsInput{TraceSegmentDocuments: documents[offset:nextOffset]}
				logger.Debug("request: " + input.String())
				output, localErr := xrayClient.PutTraceSegments(&input)
				if localErr != nil {
					logger.Debug("response error", zap.Error(localErr))
					err = wrapErrorIfBadRequest(&localErr) // record error
				}
				if output != nil {
					logger.Debug("response: " + output.String())
					if output.UnprocessedTraceSegments != nil {
						totalDroppedSpans += len(output.UnprocessedTraceSegments)
					}
				}
				if err != nil {
					break
				}
			}
			return totalDroppedSpans, err
		},
		exporterhelper.WithShutdown(func(context.Context) error {
			return logger.Sync()
		}),
	)
}

func wrapErrorIfBadRequest(err *error) error {
	_, ok := (*err).(awserr.RequestFailure)
	if ok && (*err).(awserr.RequestFailure).StatusCode() < 500 {
		return consumererror.Permanent(*err)
	}
	return *err
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 HPE Software Inc. All rights reserved.
// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.

package watch

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

	"github.com/hpcloud/tail/util"

	"gopkg.in/fsnotify.v1"
	"gopkg.in/tomb.v1"
)

// InotifyFileWatcher uses inotify to monitor file changes.
type InotifyFileWatcher struct {
	Filename string
	Size     int64
}

func NewInotifyFileWatcher(filename string) *InotifyFileWatcher {
	fw := &InotifyFileWatcher{filepath.Clean(filename), 0}
	return fw
}

func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error {
	err := WatchCreate(fw.Filename)
	if err != nil {
		return err
	}
	defer RemoveWatchCreate(fw.Filename)

	// Do a real check now as the file might have been created before
	// calling `WatchFlags` above.
	if _, err = os.Stat(fw.Filename); !os.IsNotExist(err) {
		// file exists, or stat returned an error.
		return err
	}

	events := Events(fw.Filename)

	for {
		select {
		case evt, ok := <-events:
			if !ok {
				return fmt.Errorf("inotify watcher has been closed")
			}
			evtName, err := filepath.Abs(evt.Name)
			if err != nil {
				return err
			}
			fwFilename, err := filepath.Abs(fw.Filename)
			if err != nil {
				return err
			}
			if evtName == fwFilename {
				return nil
			}
		case <-t.Dying():
			return tomb.ErrDying
		}
	}
	panic("unreachable")
}

func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) {
	err := Watch(fw.Filename)
	if err != nil {
		return nil, err
	}

	changes := NewFileChanges()
	fw.Size = pos

	go func() {

		events := Events(fw.Filename)

		for {
			prevSize := fw.Size

			var evt fsnotify.Event
			var ok bool

			select {
			case evt, ok = <-events:
				if !ok {
					RemoveWatch(fw.Filename)
					return
				}
			case <-t.Dying():
				RemoveWatch(fw.Filename)
				return
			}

			switch {
			//With an open fd, unlink(fd) - inotify returns IN_ATTRIB (==fsnotify.Chmod)
			case evt.Op&fsnotify.Chmod == fsnotify.Chmod:
				if _, err := os.Stat(fw.Filename); err != nil {
					if ! os.IsNotExist(err) {
						return
					}
				}
				fallthrough

			case evt.Op&fsnotify.Remove == fsnotify.Remove:
				fallthrough

			case evt.Op&fsnotify.Rename == fsnotify.Rename:
				RemoveWatch(fw.Filename)
				changes.NotifyDeleted()
				return

			case evt.Op&fsnotify.Write == fsnotify.Write:
				fi, err := os.Stat(fw.Filename)
				if err != nil {
					if os.IsNotExist(err) {
						RemoveWatch(fw.Filename)
						changes.NotifyDeleted()
						return
					}
					// XXX: report this error back to the user
					util.Fatal("Failed to stat file %v: %v", fw.Filename, err)
				}
				fw.Size = fi.Size()

				if prevSize > 0 && prevSize > fw.Size {
					changes.NotifyTruncated()
				} else {
					changes.NotifyModified()
				}
				prevSize = fw.Size
			}
		}
	}()

	return changes, nil
}
<commit_msg>Issue 111: TestReSeekInotify failed<commit_after>// Copyright (c) 2015 HPE Software Inc. All rights reserved.
// Copyright (c) 2013 ActiveState Software Inc. All rights reserved.

package watch

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

	"github.com/hpcloud/tail/util"

	"gopkg.in/fsnotify.v1"
	"gopkg.in/tomb.v1"
)

// InotifyFileWatcher uses inotify to monitor file changes.
type InotifyFileWatcher struct {
	Filename string
	Size     int64
}

func NewInotifyFileWatcher(filename string) *InotifyFileWatcher {
	fw := &InotifyFileWatcher{filepath.Clean(filename), 0}
	return fw
}

func (fw *InotifyFileWatcher) BlockUntilExists(t *tomb.Tomb) error {
	err := WatchCreate(fw.Filename)
	if err != nil {
		return err
	}
	defer RemoveWatchCreate(fw.Filename)

	// Do a real check now as the file might have been created before
	// calling `WatchFlags` above.
	if _, err = os.Stat(fw.Filename); !os.IsNotExist(err) {
		// file exists, or stat returned an error.
		return err
	}

	events := Events(fw.Filename)

	for {
		select {
		case evt, ok := <-events:
			if !ok {
				return fmt.Errorf("inotify watcher has been closed")
			}
			evtName, err := filepath.Abs(evt.Name)
			if err != nil {
				return err
			}
			fwFilename, err := filepath.Abs(fw.Filename)
			if err != nil {
				return err
			}
			if evtName == fwFilename {
				return nil
			}
		case <-t.Dying():
			return tomb.ErrDying
		}
	}
	panic("unreachable")
}

func (fw *InotifyFileWatcher) ChangeEvents(t *tomb.Tomb, pos int64) (*FileChanges, error) {
	err := Watch(fw.Filename)
	if err != nil {
		return nil, err
	}

	changes := NewFileChanges()
	fw.Size = pos

	go func() {

		events := Events(fw.Filename)

		for {
			prevSize := fw.Size

			var evt fsnotify.Event
			var ok bool

			select {
			case evt, ok = <-events:
				if !ok {
					RemoveWatch(fw.Filename)
					return
				}
			case <-t.Dying():
				RemoveWatch(fw.Filename)
				return
			}

			switch {
			case evt.Op&fsnotify.Remove == fsnotify.Remove:
				fallthrough

			case evt.Op&fsnotify.Rename == fsnotify.Rename:
				RemoveWatch(fw.Filename)
				changes.NotifyDeleted()
				return

			//With an open fd, unlink(fd) - inotify returns IN_ATTRIB (==fsnotify.Chmod)
			case evt.Op&fsnotify.Chmod == fsnotify.Chmod:
				fallthrough

			case evt.Op&fsnotify.Write == fsnotify.Write:
				fi, err := os.Stat(fw.Filename)
				if err != nil {
					if os.IsNotExist(err) {
						RemoveWatch(fw.Filename)
						changes.NotifyDeleted()
						return
					}
					// XXX: report this error back to the user
					util.Fatal("Failed to stat file %v: %v", fw.Filename, err)
				}
				fw.Size = fi.Size()

				if prevSize > 0 && prevSize > fw.Size {
					changes.NotifyTruncated()
				} else {
					changes.NotifyModified()
				}
				prevSize = fw.Size
			}
		}
	}()

	return changes, nil
}
<|endoftext|>


<commit_before>package watch

import (
	"fmt"
	"log"
	"sync"
	"time"

	dep "github.com/hashicorp/consul-template/dependency"
	"github.com/hashicorp/consul/api"
)

// defaultRetryFunc is the default return function, which just echos whatever
// duration it was given.
var defaultRetryFunc RetryFunc = func(t time.Duration) time.Duration {
	return t
}

// RetryFunc is a function that defines the retry for a given watcher. The
// function parameter is the current retry (which might be nil), and the
// return value is the new retry. In this way, you can build complex retry
// functions that are based off the previous values.
type RetryFunc func(time.Duration) time.Duration

type Watcher struct {
	sync.Mutex

	// once is used to determine if the views should poll for data exactly once
	once bool

	// DataCh is the chan where Views will be published
	DataCh chan *View

	// ErrCh is the chan where any errors will be published
	ErrCh chan error

	// FinishCh is the chan where the watcher reports it is "done"
	FinishCh chan struct{}

	// client is the mechanism for communicating with the Consul API
	client *api.Client

	// retryFunc is a RetryFunc that represents the way retrys and backoffs
	// should occur.
	retryFunc RetryFunc

	// depViewMap is a map of Templates to Views. Templates are keyed by
	// HashCode().
	depViewMap map[string]*View
}

// NewWatcher creates a new watcher using the given API client.
func NewWatcher(c *api.Client, once bool) (*Watcher, error) {
	watcher := &Watcher{
		client: c,
		once:   once,
	}
	if err := watcher.init(); err != nil {
		return nil, err
	}

	return watcher, nil
}

// Add adds the given dependency to the list of monitored depedencies
// and start the associated view. If the dependency already exists, no action is
// taken.
//
// If the Dependency already existed, it this function will return false. If the
// view was successfully created, it will return true. If an error occurs while
// creating the view, it will be returned here (but future errors returned by
// the view will happen on the channel).
func (w *Watcher) Add(d dep.Dependency) (bool, error) {
	w.Lock()
	defer w.Unlock()

	log.Printf("[INFO] (watcher) adding %s", d.Display())

	if _, ok := w.depViewMap[d.HashCode()]; ok {
		log.Printf("[DEBUG] (watcher) %s already exists, skipping", d.Display())
		return false, nil
	}

	v, err := NewView(w.client, d)
	if err != nil {
		return false, err
	}

	log.Printf("[DEBUG] (watcher) %s starting", d.Display())

	w.depViewMap[d.HashCode()] = v
	go v.poll(w.once, w.DataCh, w.ErrCh, w.retryFunc)

	return true, nil
}

// Watching determines if the given dependency is being watched.
func (w *Watcher) Watching(d dep.Dependency) bool {
	w.Lock()
	defer w.Unlock()

	_, ok := w.depViewMap[d.HashCode()]
	return ok
}

// Remove removes the given dependency from the list and stops the
// associated View. If a View for the given dependency does not exist, this
// function will return false. If the View does exist, this function will return
// true upon successful deletion.
func (w *Watcher) Remove(d dep.Dependency) bool {
	w.Lock()
	defer w.Unlock()

	log.Printf("[INFO] (watcher) removing %s", d.Display())

	if view, ok := w.depViewMap[d.HashCode()]; ok {
		log.Printf("[DEBUG] (watcher) actually removing %s", d.Display())
		view.stop()
		delete(w.depViewMap, d.HashCode())
		return true
	}

	log.Printf("[DEBUG] (watcher) %s did not exist, skipping", d.Display())
	return false
}

// SetRetry is used to set the retry to a static value. See SetRetryFunc for
// more informatoin.
func (w *Watcher) SetRetry(duration time.Duration) {
	w.SetRetryFunc(func(current time.Duration) time.Duration {
		return duration
	})
}

// SetRetryFunc is used to set a dynamic retry function. Only new views created
// after this function has been set will inherit the new retry functionality.
// Existing views will use the retry functionality with which they were created.
func (w *Watcher) SetRetryFunc(f RetryFunc) {
	w.Lock()
	defer w.Unlock()
	w.retryFunc = f
}

// Stop halts this watcher and any currently polling views immediately. If a
// view was in the middle of a poll, no data will be returned.
func (w *Watcher) Stop() {
	log.Printf("[INFO] (watcher) stopping all views")

	for _, view := range w.depViewMap {
		log.Printf("[DEBUG] (watcher) stopping %+v", view)
		view.stop()
	}
}

// init sets up the initial values for the watcher.
func (w *Watcher) init() error {
	if w.client == nil {
		return fmt.Errorf("watcher: missing Consul API client")
	}

	// Setup the channels
	w.DataCh = make(chan *View)
	w.ErrCh = make(chan error)
	w.FinishCh = make(chan struct{})

	// Setup the default retry
	w.SetRetryFunc(defaultRetryFunc)

	// Setup our map of dependencies to views
	w.depViewMap = make(map[string]*View)

	return nil
}
<commit_msg>Lock and reset the viewDepMap in the Watcher<commit_after>package watch

import (
	"fmt"
	"log"
	"sync"
	"time"

	dep "github.com/hashicorp/consul-template/dependency"
	"github.com/hashicorp/consul/api"
)

// defaultRetryFunc is the default return function, which just echos whatever
// duration it was given.
var defaultRetryFunc RetryFunc = func(t time.Duration) time.Duration {
	return t
}

// RetryFunc is a function that defines the retry for a given watcher. The
// function parameter is the current retry (which might be nil), and the
// return value is the new retry. In this way, you can build complex retry
// functions that are based off the previous values.
type RetryFunc func(time.Duration) time.Duration

type Watcher struct {
	sync.Mutex

	// once is used to determine if the views should poll for data exactly once
	once bool

	// DataCh is the chan where Views will be published
	DataCh chan *View

	// ErrCh is the chan where any errors will be published
	ErrCh chan error

	// FinishCh is the chan where the watcher reports it is "done"
	FinishCh chan struct{}

	// client is the mechanism for communicating with the Consul API
	client *api.Client

	// retryFunc is a RetryFunc that represents the way retrys and backoffs
	// should occur.
	retryFunc RetryFunc

	// depViewMap is a map of Templates to Views. Templates are keyed by
	// HashCode().
	depViewMap map[string]*View
}

// NewWatcher creates a new watcher using the given API client.
func NewWatcher(c *api.Client, once bool) (*Watcher, error) {
	watcher := &Watcher{
		client: c,
		once:   once,
	}
	if err := watcher.init(); err != nil {
		return nil, err
	}

	return watcher, nil
}

// Add adds the given dependency to the list of monitored depedencies
// and start the associated view. If the dependency already exists, no action is
// taken.
//
// If the Dependency already existed, it this function will return false. If the
// view was successfully created, it will return true. If an error occurs while
// creating the view, it will be returned here (but future errors returned by
// the view will happen on the channel).
func (w *Watcher) Add(d dep.Dependency) (bool, error) {
	w.Lock()
	defer w.Unlock()

	log.Printf("[INFO] (watcher) adding %s", d.Display())

	if _, ok := w.depViewMap[d.HashCode()]; ok {
		log.Printf("[DEBUG] (watcher) %s already exists, skipping", d.Display())
		return false, nil
	}

	v, err := NewView(w.client, d)
	if err != nil {
		return false, err
	}

	log.Printf("[DEBUG] (watcher) %s starting", d.Display())

	w.depViewMap[d.HashCode()] = v
	go v.poll(w.once, w.DataCh, w.ErrCh, w.retryFunc)

	return true, nil
}

// Watching determines if the given dependency is being watched.
func (w *Watcher) Watching(d dep.Dependency) bool {
	w.Lock()
	defer w.Unlock()

	_, ok := w.depViewMap[d.HashCode()]
	return ok
}

// Remove removes the given dependency from the list and stops the
// associated View. If a View for the given dependency does not exist, this
// function will return false. If the View does exist, this function will return
// true upon successful deletion.
func (w *Watcher) Remove(d dep.Dependency) bool {
	w.Lock()
	defer w.Unlock()

	log.Printf("[INFO] (watcher) removing %s", d.Display())

	if view, ok := w.depViewMap[d.HashCode()]; ok {
		log.Printf("[DEBUG] (watcher) actually removing %s", d.Display())
		view.stop()
		delete(w.depViewMap, d.HashCode())
		return true
	}

	log.Printf("[DEBUG] (watcher) %s did not exist, skipping", d.Display())
	return false
}

// SetRetry is used to set the retry to a static value. See SetRetryFunc for
// more informatoin.
func (w *Watcher) SetRetry(duration time.Duration) {
	w.SetRetryFunc(func(current time.Duration) time.Duration {
		return duration
	})
}

// SetRetryFunc is used to set a dynamic retry function. Only new views created
// after this function has been set will inherit the new retry functionality.
// Existing views will use the retry functionality with which they were created.
func (w *Watcher) SetRetryFunc(f RetryFunc) {
	w.Lock()
	defer w.Unlock()
	w.retryFunc = f
}

// Stop halts this watcher and any currently polling views immediately. If a
// view was in the middle of a poll, no data will be returned.
func (w *Watcher) Stop() {
	w.Lock()
	defer w.Unlock()

	log.Printf("[INFO] (watcher) stopping all views")

	for _, view := range w.depViewMap {
		log.Printf("[DEBUG] (watcher) stopping %+v", view)
		view.stop()
	}

	// Reset the map to have no views
	w.depViewMap = make(map[string]*View)
}

// init sets up the initial values for the watcher.
func (w *Watcher) init() error {
	if w.client == nil {
		return fmt.Errorf("watcher: missing Consul API client")
	}

	// Setup the channels
	w.DataCh = make(chan *View)
	w.ErrCh = make(chan error)
	w.FinishCh = make(chan struct{})

	// Setup the default retry
	w.SetRetryFunc(defaultRetryFunc)

	// Setup our map of dependencies to views
	w.depViewMap = make(map[string]*View)

	return nil
}
<|endoftext|>


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

package parser

import (
	"go/ast";
	"go/parser";
	"os";
	"testing";
)

var illegalInputs = []interface{} {
	nil,
	3.14,
	[]byte(nil),
	"foo!",
}

func TestParseIllegalInputs(t *testing.T) {
	for _, src := range illegalInputs {
		prog, err := Parse(src, 0);
		if err == nil {
			t.Errorf("Parse(%v) should have failed", src);
		}
	}
}

var validPrograms = []interface{} {
	`package main`,
	`package main import "fmt" func main() { fmt.Println("Hello, World!") }`,
}

func TestParseValidPrograms(t *testing.T) {
	for _, src := range validPrograms {
		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%q) failed: %v", src, err);
		}
	}
}

var validFiles = []string {
	"parser.go",
	"parser_test.go",
}

func TestParse3(t *testing.T) {
	for _, filename := range validFiles {
		src, err := os.Open(filename, os.O_RDONLY, 0);
		defer src.Close();
		if err != nil {
			t.Fatalf("os.Open(%s): %v\n", filename, err);
		}

		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%q): %v", src, err);
		}
	}
}
<commit_msg>fix error messages<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package parser

import (
	"go/ast";
	"go/parser";
	"os";
	"testing";
)

var illegalInputs = []interface{} {
	nil,
	3.14,
	[]byte(nil),
	"foo!",
}

func TestParseIllegalInputs(t *testing.T) {
	for _, src := range illegalInputs {
		prog, err := Parse(src, 0);
		if err == nil {
			t.Errorf("Parse(%v) should have failed", src);
		}
	}
}

var validPrograms = []interface{} {
	`package main`,
	`package main import "fmt" func main() { fmt.Println("Hello, World!") }`,
}

func TestParseValidPrograms(t *testing.T) {
	for _, src := range validPrograms {
		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%q) failed: %v", src, err);
		}
	}
}

var validFiles = []string {
	"parser.go",
	"parser_test.go",
}

func TestParse3(t *testing.T) {
	for _, filename := range validFiles {
		src, err := os.Open(filename, os.O_RDONLY, 0);
		defer src.Close();
		if err != nil {
			t.Fatal(err);
		}

		prog, err := Parse(src, 0);
		if err != nil {
			t.Errorf("Parse(%s): %v", filename, err);
		}
	}
}
<|endoftext|>


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

package http_test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	. "net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"reflect"
	"regexp"
	"strings"
	"testing"
)

func TestQuery(t *testing.T) {
	req := &Request{Method: "GET"}
	req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
	if q := req.FormValue("q"); q != "foo" {
		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
	}
}

func TestPostQuery(t *testing.T) {
	req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x",
		strings.NewReader("z=post&both=y"))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")

	if q := req.FormValue("q"); q != "foo" {
		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
	}
	if z := req.FormValue("z"); z != "post" {
		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
	}
	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
		t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
	}
}

type stringMap map[string][]string
type parseContentTypeTest struct {
	contentType stringMap
}

var parseContentTypeTests = []parseContentTypeTest{
	{contentType: stringMap{"Content-Type": {"text/plain"}}},
	{contentType: stringMap{}}, // Non-existent keys are not placed. The value nil is illegal.
	{contentType: stringMap{"Content-Type": {"text/plain; boundary="}}},
	{
		contentType: stringMap{"Content-Type": {"application/unknown"}},
	},
}

func TestParseFormBadContentType(t *testing.T) {
	for i, test := range parseContentTypeTests {
		req := &Request{
			Method: "POST",
			Header: Header(test.contentType),
			Body:   ioutil.NopCloser(bytes.NewBufferString("body")),
		}
		err := req.ParseForm()
		if err == nil {
			t.Errorf("test %d should have returned error", i)
		}
	}
}

func TestMultipartReader(t *testing.T) {
	req := &Request{
		Method: "POST",
		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
		Body:   ioutil.NopCloser(new(bytes.Buffer)),
	}
	multipart, err := req.MultipartReader()
	if multipart == nil {
		t.Errorf("expected multipart; error: %v", err)
	}

	req.Header = Header{"Content-Type": {"text/plain"}}
	multipart, err = req.MultipartReader()
	if multipart != nil {
		t.Errorf("unexpected multipart for text/plain")
	}
}

func TestRedirect(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		switch r.URL.Path {
		case "/":
			w.Header().Set("Location", "/foo/")
			w.WriteHeader(StatusSeeOther)
		case "/foo/":
			fmt.Fprintf(w, "foo")
		default:
			w.WriteHeader(StatusBadRequest)
		}
	}))
	defer ts.Close()

	var end = regexp.MustCompile("/foo/$")
	r, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	r.Body.Close()
	url := r.Request.URL.String()
	if r.StatusCode != 200 || !end.MatchString(url) {
		t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
	}
}

func TestSetBasicAuth(t *testing.T) {
	r, _ := NewRequest("GET", "http://example.com/", nil)
	r.SetBasicAuth("Aladdin", "open sesame")
	if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
		t.Errorf("got header %q, want %q", g, e)
	}
}

func TestMultipartRequest(t *testing.T) {
	// Test that we can read the values and files of a
	// multipart request with FormValue and FormFile,
	// and that ParseMultipartForm can be called multiple times.
	req := newTestMultipartRequest(t)
	if err := req.ParseMultipartForm(25); err != nil {
		t.Fatal("ParseMultipartForm first call:", err)
	}
	defer req.MultipartForm.RemoveAll()
	validateTestMultipartContents(t, req, false)
	if err := req.ParseMultipartForm(25); err != nil {
		t.Fatal("ParseMultipartForm second call:", err)
	}
	validateTestMultipartContents(t, req, false)
}

func TestMultipartRequestAuto(t *testing.T) {
	// Test that FormValue and FormFile automatically invoke
	// ParseMultipartForm and return the right values.
	req := newTestMultipartRequest(t)
	defer func() {
		if req.MultipartForm != nil {
			req.MultipartForm.RemoveAll()
		}
	}()
	validateTestMultipartContents(t, req, true)
}

func TestEmptyMultipartRequest(t *testing.T) {
	// Test that FormValue and FormFile automatically invoke
	// ParseMultipartForm and return the right values.
	req, err := NewRequest("GET", "/", nil)
	if err != nil {
		t.Errorf("NewRequest err = %q", err)
	}
	testMissingFile(t, req)
}

func TestRequestMultipartCallOrder(t *testing.T) {
	req := newTestMultipartRequest(t)
	_, err := req.MultipartReader()
	if err != nil {
		t.Fatalf("MultipartReader: %v", err)
	}
	err = req.ParseMultipartForm(1024)
	if err == nil {
		t.Errorf("expected an error from ParseMultipartForm after call to MultipartReader")
	}
}

func testMissingFile(t *testing.T, req *Request) {
	f, fh, err := req.FormFile("missing")
	if f != nil {
		t.Errorf("FormFile file = %q, want nil", f)
	}
	if fh != nil {
		t.Errorf("FormFile file header = %q, want nil", fh)
	}
	if err != ErrMissingFile {
		t.Errorf("FormFile err = %q, want ErrMissingFile", err)
	}
}

func newTestMultipartRequest(t *testing.T) *Request {
	b := bytes.NewBufferString(strings.Replace(message, "\n", "\r\n", -1))
	req, err := NewRequest("POST", "/", b)
	if err != nil {
		t.Fatal("NewRequest:", err)
	}
	ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
	req.Header.Set("Content-type", ctype)
	return req
}

func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
	if g, e := req.FormValue("texta"), textaValue; g != e {
		t.Errorf("texta value = %q, want %q", g, e)
	}
	if g, e := req.FormValue("texta"), textaValue; g != e {
		t.Errorf("texta value = %q, want %q", g, e)
	}
	if g := req.FormValue("missing"); g != "" {
		t.Errorf("missing value = %q, want empty string", g)
	}

	assertMem := func(n string, fd multipart.File) {
		if _, ok := fd.(*os.File); ok {
			t.Error(n, " is *os.File, should not be")
		}
	}
	fd := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
	assertMem("filea", fd)
	fd = testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
	if allMem {
		assertMem("fileb", fd)
	} else {
		if _, ok := fd.(*os.File); !ok {
			t.Errorf("fileb has unexpected underlying type %T", fd)
		}
	}

	testMissingFile(t, req)
}

func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
	f, fh, err := req.FormFile(key)
	if err != nil {
		t.Fatalf("FormFile(%q): %q", key, err)
	}
	if fh.Filename != expectFilename {
		t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
	}
	var b bytes.Buffer
	_, err = io.Copy(&b, f)
	if err != nil {
		t.Fatal("copying contents:", err)
	}
	if g := b.String(); g != expectContent {
		t.Errorf("contents = %q, want %q", g, expectContent)
	}
	return f
}

const (
	fileaContents = "This is a test file."
	filebContents = "Another test file."
	textaValue    = "foo"
	textbValue    = "bar"
	boundary      = `MyBoundary`
)

const message = `
--MyBoundary
Content-Disposition: form-data; name="filea"; filename="filea.txt"
Content-Type: text/plain

` + fileaContents + `
--MyBoundary
Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
Content-Type: text/plain

` + filebContents + `
--MyBoundary
Content-Disposition: form-data; name="texta"

` + textaValue + `
--MyBoundary
Content-Disposition: form-data; name="textb"

` + textbValue + `
--MyBoundary--
`
<commit_msg>net/http: test both texta and textb values, not texta twice<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http_test

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	. "net/http"
	"net/http/httptest"
	"net/url"
	"os"
	"reflect"
	"regexp"
	"strings"
	"testing"
)

func TestQuery(t *testing.T) {
	req := &Request{Method: "GET"}
	req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
	if q := req.FormValue("q"); q != "foo" {
		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
	}
}

func TestPostQuery(t *testing.T) {
	req, _ := NewRequest("POST", "http://www.google.com/search?q=foo&q=bar&both=x",
		strings.NewReader("z=post&both=y"))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")

	if q := req.FormValue("q"); q != "foo" {
		t.Errorf(`req.FormValue("q") = %q, want "foo"`, q)
	}
	if z := req.FormValue("z"); z != "post" {
		t.Errorf(`req.FormValue("z") = %q, want "post"`, z)
	}
	if both := req.Form["both"]; !reflect.DeepEqual(both, []string{"x", "y"}) {
		t.Errorf(`req.FormValue("both") = %q, want ["x", "y"]`, both)
	}
}

type stringMap map[string][]string
type parseContentTypeTest struct {
	contentType stringMap
}

var parseContentTypeTests = []parseContentTypeTest{
	{contentType: stringMap{"Content-Type": {"text/plain"}}},
	{contentType: stringMap{}}, // Non-existent keys are not placed. The value nil is illegal.
	{contentType: stringMap{"Content-Type": {"text/plain; boundary="}}},
	{
		contentType: stringMap{"Content-Type": {"application/unknown"}},
	},
}

func TestParseFormBadContentType(t *testing.T) {
	for i, test := range parseContentTypeTests {
		req := &Request{
			Method: "POST",
			Header: Header(test.contentType),
			Body:   ioutil.NopCloser(bytes.NewBufferString("body")),
		}
		err := req.ParseForm()
		if err == nil {
			t.Errorf("test %d should have returned error", i)
		}
	}
}

func TestMultipartReader(t *testing.T) {
	req := &Request{
		Method: "POST",
		Header: Header{"Content-Type": {`multipart/form-data; boundary="foo123"`}},
		Body:   ioutil.NopCloser(new(bytes.Buffer)),
	}
	multipart, err := req.MultipartReader()
	if multipart == nil {
		t.Errorf("expected multipart; error: %v", err)
	}

	req.Header = Header{"Content-Type": {"text/plain"}}
	multipart, err = req.MultipartReader()
	if multipart != nil {
		t.Errorf("unexpected multipart for text/plain")
	}
}

func TestRedirect(t *testing.T) {
	ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
		switch r.URL.Path {
		case "/":
			w.Header().Set("Location", "/foo/")
			w.WriteHeader(StatusSeeOther)
		case "/foo/":
			fmt.Fprintf(w, "foo")
		default:
			w.WriteHeader(StatusBadRequest)
		}
	}))
	defer ts.Close()

	var end = regexp.MustCompile("/foo/$")
	r, err := Get(ts.URL)
	if err != nil {
		t.Fatal(err)
	}
	r.Body.Close()
	url := r.Request.URL.String()
	if r.StatusCode != 200 || !end.MatchString(url) {
		t.Fatalf("Get got status %d at %q, want 200 matching /foo/$", r.StatusCode, url)
	}
}

func TestSetBasicAuth(t *testing.T) {
	r, _ := NewRequest("GET", "http://example.com/", nil)
	r.SetBasicAuth("Aladdin", "open sesame")
	if g, e := r.Header.Get("Authorization"), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="; g != e {
		t.Errorf("got header %q, want %q", g, e)
	}
}

func TestMultipartRequest(t *testing.T) {
	// Test that we can read the values and files of a
	// multipart request with FormValue and FormFile,
	// and that ParseMultipartForm can be called multiple times.
	req := newTestMultipartRequest(t)
	if err := req.ParseMultipartForm(25); err != nil {
		t.Fatal("ParseMultipartForm first call:", err)
	}
	defer req.MultipartForm.RemoveAll()
	validateTestMultipartContents(t, req, false)
	if err := req.ParseMultipartForm(25); err != nil {
		t.Fatal("ParseMultipartForm second call:", err)
	}
	validateTestMultipartContents(t, req, false)
}

func TestMultipartRequestAuto(t *testing.T) {
	// Test that FormValue and FormFile automatically invoke
	// ParseMultipartForm and return the right values.
	req := newTestMultipartRequest(t)
	defer func() {
		if req.MultipartForm != nil {
			req.MultipartForm.RemoveAll()
		}
	}()
	validateTestMultipartContents(t, req, true)
}

func TestEmptyMultipartRequest(t *testing.T) {
	// Test that FormValue and FormFile automatically invoke
	// ParseMultipartForm and return the right values.
	req, err := NewRequest("GET", "/", nil)
	if err != nil {
		t.Errorf("NewRequest err = %q", err)
	}
	testMissingFile(t, req)
}

func TestRequestMultipartCallOrder(t *testing.T) {
	req := newTestMultipartRequest(t)
	_, err := req.MultipartReader()
	if err != nil {
		t.Fatalf("MultipartReader: %v", err)
	}
	err = req.ParseMultipartForm(1024)
	if err == nil {
		t.Errorf("expected an error from ParseMultipartForm after call to MultipartReader")
	}
}

func testMissingFile(t *testing.T, req *Request) {
	f, fh, err := req.FormFile("missing")
	if f != nil {
		t.Errorf("FormFile file = %q, want nil", f)
	}
	if fh != nil {
		t.Errorf("FormFile file header = %q, want nil", fh)
	}
	if err != ErrMissingFile {
		t.Errorf("FormFile err = %q, want ErrMissingFile", err)
	}
}

func newTestMultipartRequest(t *testing.T) *Request {
	b := bytes.NewBufferString(strings.Replace(message, "\n", "\r\n", -1))
	req, err := NewRequest("POST", "/", b)
	if err != nil {
		t.Fatal("NewRequest:", err)
	}
	ctype := fmt.Sprintf(`multipart/form-data; boundary="%s"`, boundary)
	req.Header.Set("Content-type", ctype)
	return req
}

func validateTestMultipartContents(t *testing.T, req *Request, allMem bool) {
	if g, e := req.FormValue("texta"), textaValue; g != e {
		t.Errorf("texta value = %q, want %q", g, e)
	}
	if g, e := req.FormValue("textb"), textbValue; g != e {
		t.Errorf("textb value = %q, want %q", g, e)
	}
	if g := req.FormValue("missing"); g != "" {
		t.Errorf("missing value = %q, want empty string", g)
	}

	assertMem := func(n string, fd multipart.File) {
		if _, ok := fd.(*os.File); ok {
			t.Error(n, " is *os.File, should not be")
		}
	}
	fd := testMultipartFile(t, req, "filea", "filea.txt", fileaContents)
	assertMem("filea", fd)
	fd = testMultipartFile(t, req, "fileb", "fileb.txt", filebContents)
	if allMem {
		assertMem("fileb", fd)
	} else {
		if _, ok := fd.(*os.File); !ok {
			t.Errorf("fileb has unexpected underlying type %T", fd)
		}
	}

	testMissingFile(t, req)
}

func testMultipartFile(t *testing.T, req *Request, key, expectFilename, expectContent string) multipart.File {
	f, fh, err := req.FormFile(key)
	if err != nil {
		t.Fatalf("FormFile(%q): %q", key, err)
	}
	if fh.Filename != expectFilename {
		t.Errorf("filename = %q, want %q", fh.Filename, expectFilename)
	}
	var b bytes.Buffer
	_, err = io.Copy(&b, f)
	if err != nil {
		t.Fatal("copying contents:", err)
	}
	if g := b.String(); g != expectContent {
		t.Errorf("contents = %q, want %q", g, expectContent)
	}
	return f
}

const (
	fileaContents = "This is a test file."
	filebContents = "Another test file."
	textaValue    = "foo"
	textbValue    = "bar"
	boundary      = `MyBoundary`
)

const message = `
--MyBoundary
Content-Disposition: form-data; name="filea"; filename="filea.txt"
Content-Type: text/plain

` + fileaContents + `
--MyBoundary
Content-Disposition: form-data; name="fileb"; filename="fileb.txt"
Content-Type: text/plain

` + filebContents + `
--MyBoundary
Content-Disposition: form-data; name="texta"

` + textaValue + `
--MyBoundary
Content-Disposition: form-data; name="textb"

` + textbValue + `
--MyBoundary--
`
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"time"

	"github.com/alexflint/go-arg"
	"github.com/pkg/profile"
	"github.com/walle/cc"
)

var args struct {
	Columns int `arg:"-c,required,help:the number of columns to use on the board"`
	Rows    int `arg:"-r,required,help:the number of rows to use on the board"`
	Kings   int `arg:"-k,help:the number of kings to use on the board"`
	Queens  int `arg:"-q,help:the number of queens to use on the board"`
	Bishops int `arg:"-b,help:the number of bishops to use on the board"`
	Rooks   int `arg:"-t,help:the number of rooks to use on the board"`
	Knights int `arg:"-n,help:the number of knights to use on the board"`
}

func main() {
	defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
	//defer profile.Start(profile.BlockProfile, profile.ProfilePath(".")).Stop()
	//defer profile.Start(profile.MemProfile, profile.ProfilePath(".")).Stop()
	arg.MustParse(&args)
	start := time.Now()

	n := args.Kings + args.Queens + args.Bishops + args.Rooks + args.Knights
	pieces := make([]cc.Piece, 0, n)
	for i := 0; i < args.Queens; i++ {
		pieces = append(pieces, cc.Queen)
	}
	for i := 0; i < args.Rooks; i++ {
		pieces = append(pieces, cc.Rook)
	}
	for i := 0; i < args.Bishops; i++ {
		pieces = append(pieces, cc.Bishop)
	}
	for i := 0; i < args.Knights; i++ {
		pieces = append(pieces, cc.Knight)
	}
	for i := 0; i < args.Kings; i++ {
		pieces = append(pieces, cc.King)
	}

	solutions := make(map[string]bool)
	cc.Solve(uint8(args.Columns), uint8(args.Rows), pieces, &solutions)

	combs := ""
	for k := range solutions {
		combs += k + "; "
	}

	fmt.Printf("[%d] %s(%s)\n", len(solutions), combs, time.Now().Sub(start))
}
<commit_msg>Remove profiling code<commit_after>package main

import (
	"fmt"
	"time"

	"github.com/alexflint/go-arg"
	"github.com/walle/cc"
)

var args struct {
	Columns int `arg:"-c,required,help:the number of columns to use on the board"`
	Rows    int `arg:"-r,required,help:the number of rows to use on the board"`
	Kings   int `arg:"-k,help:the number of kings to use on the board"`
	Queens  int `arg:"-q,help:the number of queens to use on the board"`
	Bishops int `arg:"-b,help:the number of bishops to use on the board"`
	Rooks   int `arg:"-t,help:the number of rooks to use on the board"`
	Knights int `arg:"-n,help:the number of knights to use on the board"`
}

func main() {
	arg.MustParse(&args)
	start := time.Now()

	n := args.Kings + args.Queens + args.Bishops + args.Rooks + args.Knights
	pieces := make([]cc.Piece, 0, n)
	for i := 0; i < args.Queens; i++ {
		pieces = append(pieces, cc.Queen)
	}
	for i := 0; i < args.Rooks; i++ {
		pieces = append(pieces, cc.Rook)
	}
	for i := 0; i < args.Bishops; i++ {
		pieces = append(pieces, cc.Bishop)
	}
	for i := 0; i < args.Knights; i++ {
		pieces = append(pieces, cc.Knight)
	}
	for i := 0; i < args.Kings; i++ {
		pieces = append(pieces, cc.King)
	}

	solutions := make(map[string]bool)
	cc.Solve(uint8(args.Columns), uint8(args.Rows), pieces, &solutions)

	combs := ""
	for k := range solutions {
		combs += k + "; "
	}

	fmt.Printf("[%d] %s(%s)\n", len(solutions), combs, time.Now().Sub(start))
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"time"

	"encoding/json"
	"io/ioutil"

	"github.com/aleasoluciones/felixcheck"
	"github.com/aleasoluciones/gosnmpquerier"
)

type Device struct {
	Id        string
	DevType   string
	Ip        string
	Community string
}

func devicesFromInventory(inventoryPath string) ([]Device, error) {
	content, err := ioutil.ReadFile(inventoryPath)
	if err != nil {
		return []Device{}, err
	}
	var inventory interface{}
	err = json.Unmarshal(content, &inventory)
	if err != nil {
		return []Device{}, err
	}

	devices := []Device{}

	for _, device := range inventory.([]interface{}) {
		deviceMap := device.(map[string]interface{})
		status := deviceMap["status"].(string)
		if status == "Activo" {
			device := Device{
				DevType: deviceMap["dev_type"].(string),
				Id:      deviceMap["id"].(string),
				Ip:      deviceMap["ip"].(string),
			}
			community, ok := deviceMap["snmp_rw"]
			if ok {
				device.Community = community.(string)
			}
			devices = append(devices, device)
		}
	}
	return devices, nil
}

type ConsoleLogPublisher struct {
}

func main() {
	devices, err := devicesFromInventory(os.Getenv("INVENTORY_FILE"))
	if err != nil {
		log.Panic(err)
	}

	var amqpuri, exchange string

	flag.StringVar(&amqpuri, "amqpuri", "amqp://guest:guest@localhost/", "AMQP connection uri")
	flag.StringVar(&exchange, "exchange", "events", "AMQP exchange")
	flag.Parse()

	publisher := felixcheck.NewRabbitMqPublisher(amqpuri, exchange)

	checkEngine := felixcheck.NewCheckEngine(publisher)
	snmpQuerier := gosnmpquerier.NewSyncQuerier(1, 1, 4*time.Second)

	for _, device := range devices {
		if device.DevType == "bos" {
			checkEngine.AddCheck(device.Id, "tcport", 20*time.Second, felixcheck.NewTcpPortChecker(device.Ip, 6922, felixcheck.DefaultTcpCheckConf))
			checkEngine.AddCheck(device.Id, "ping", 20*time.Second, felixcheck.NewPingCheck(device.Ip))
		} else {
			checkEngine.AddCheck(device.Id, "ping", 20*time.Second, felixcheck.NewPingCheck(device.Ip))
		}

		if device.Community != "" {
			checkEngine.AddCheck(device.Id, "snmp", 20*time.Second,
				felixcheck.NewSnmpChecker(device.Ip, device.Community, felixcheck.DefaultSnmpCheckConf, snmpQuerier))
		}
	}
	checkEngine.AddCheck("golang", "http", 30*time.Second, felixcheck.NewHttpChecker("http://golang.org/", 200))

	for {
		time.Sleep(2 * time.Second)
	}
}
<commit_msg>Removed main<commit_after><|endoftext|>