<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/google/syzkaller/fileutil"
	"github.com/google/syzkaller/sys"
	"github.com/google/syzkaller/vm"
)

type Config struct {
	Name     string // Instance name (used for identification and as GCE instance prefix)
	Http     string // TCP address to serve HTTP stats page (e.g. "localhost:50000")
	Rpc      string // TCP address to serve RPC for fuzzer processes (optional, only useful for type "none")
	Workdir  string
	Vmlinux  string
	Kernel   string // e.g. arch/x86/boot/bzImage
	Tag      string // arbitrary optional tag that is saved along with crash reports (e.g. kernel branch/commit)
	Cmdline  string // kernel command line
	Image    string // linux image for VMs
	Initrd   string // linux initial ramdisk. (optional)
	Cpu      int    // number of VM CPUs
	Mem      int    // amount of VM memory in MBs
	Sshkey   string // root ssh key for the image
	Bin      string // qemu/lkvm binary name
	Bin_Args string // additional command line arguments for qemu/lkvm binary
	Debug    bool   // dump all VM output to console
	Output   string // one of stdout/dmesg/file (useful only for local VM)

	Hub_Addr string
	Hub_Key  string

	Syzkaller string   // path to syzkaller checkout (syz-manager will look for binaries in bin subdir)
	Type      string   // VM type (qemu, kvm, local)
	Count     int      // number of VMs (don't secify for adb, instead specify devices)
	Devices   []string // device IDs for adb
	Procs     int      // number of parallel processes inside of every VM

	Sandbox string // type of sandbox to use during fuzzing:
	// "none": don't do anything special (has false positives, e.g. due to killing init)
	// "setuid": impersonate into user nobody (65534), default
	// "namespace": create a new namespace for fuzzer using CLONE_NEWNS/CLONE_NEWNET/CLONE_NEWPID/etc,
	//	requires building kernel with CONFIG_NAMESPACES, CONFIG_UTS_NS, CONFIG_USER_NS, CONFIG_PID_NS and CONFIG_NET_NS.

	Machine_Type string // GCE machine type (e.g. "n1-highcpu-2")

	Cover     bool // use kcov coverage (default: true)
	Leak      bool // do memory leak checking
	Reproduce bool // reproduce, localize and minimize crashers (on by default)

	Enable_Syscalls  []string
	Disable_Syscalls []string
	Suppressions     []string // don't save reports matching these regexps, but reboot VM after them
	Ignores          []string // completely ignore reports matching these regexps (don't save nor reboot)

	// Implementation details beyond this point.
	ParsedSuppressions []*regexp.Regexp `json:"-"`
	ParsedIgnores      []*regexp.Regexp `json:"-"`
}

func Parse(filename string) (*Config, map[int]bool, error) {
	if filename == "" {
		return nil, nil, fmt.Errorf("supply config in -config flag")
	}
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to read config file: %v", err)
	}
	return parse(data)
}

func parse(data []byte) (*Config, map[int]bool, error) {
	unknown, err := checkUnknownFields(data)
	if err != nil {
		return nil, nil, err
	}
	if unknown != "" {
		return nil, nil, fmt.Errorf("unknown field '%v' in config", unknown)
	}
	cfg := new(Config)
	cfg.Cover = true
	cfg.Reproduce = true
	cfg.Sandbox = "setuid"
	if err := json.Unmarshal(data, cfg); err != nil {
		return nil, nil, fmt.Errorf("failed to parse config file: %v", err)
	}
	if _, err := os.Stat(filepath.Join(cfg.Syzkaller, "bin/syz-fuzzer")); err != nil {
		return nil, nil, fmt.Errorf("bad config syzkaller param: can't find bin/syz-fuzzer")
	}
	if _, err := os.Stat(filepath.Join(cfg.Syzkaller, "bin/syz-executor")); err != nil {
		return nil, nil, fmt.Errorf("bad config syzkaller param: can't find bin/syz-executor")
	}
	if cfg.Http == "" {
		return nil, nil, fmt.Errorf("config param http is empty")
	}
	if cfg.Workdir == "" {
		return nil, nil, fmt.Errorf("config param workdir is empty")
	}
	if cfg.Vmlinux == "" {
		return nil, nil, fmt.Errorf("config param vmlinux is empty")
	}
	if cfg.Type == "" {
		return nil, nil, fmt.Errorf("config param type is empty")
	}
	switch cfg.Type {
	case "none":
		if cfg.Count != 0 {
			return nil, nil, fmt.Errorf("invalid config param count: %v, type \"none\" does not support param count", cfg.Count)
		}
		if cfg.Rpc == "" {
			return nil, nil, fmt.Errorf("config param rpc is empty (required for type \"none\")")
		}
		if len(cfg.Devices) != 0 {
			return nil, nil, fmt.Errorf("type %v does not support devices param", cfg.Type)
		}
	case "adb":
		if cfg.Count != 0 {
			return nil, nil, fmt.Errorf("don't specify count for adb, instead specify devices")
		}
		if len(cfg.Devices) == 0 {
			return nil, nil, fmt.Errorf("specify at least 1 adb device")
		}
		cfg.Count = len(cfg.Devices)
	case "gce":
		if cfg.Machine_Type == "" {
			return nil, nil, fmt.Errorf("machine_type parameter is empty (required for gce)")
		}
		fallthrough
	default:
		if cfg.Count <= 0 || cfg.Count > 1000 {
			return nil, nil, fmt.Errorf("invalid config param count: %v, want (1, 1000]", cfg.Count)
		}
		if len(cfg.Devices) != 0 {
			return nil, nil, fmt.Errorf("type %v does not support devices param", cfg.Type)
		}
	}
	if cfg.Rpc == "" {
		cfg.Rpc = "localhost:0"
	}
	if cfg.Procs <= 0 {
		cfg.Procs = 1
	}
	if cfg.Procs > 32 {
		return nil, nil, fmt.Errorf("config param procs has higher value '%v' then the max supported 32", cfg.Procs)
	}
	if cfg.Output == "" {
		if cfg.Type == "local" {
			cfg.Output = "none"
		} else {
			cfg.Output = "stdout"
		}
	}
	switch cfg.Output {
	case "none", "stdout", "dmesg", "file":
	default:
		return nil, nil, fmt.Errorf("config param output must contain one of none/stdout/dmesg/file")
	}
	switch cfg.Sandbox {
	case "none", "setuid", "namespace":
	default:
		return nil, nil, fmt.Errorf("config param sandbox must contain one of none/setuid/namespace")
	}

	syscalls, err := parseSyscalls(cfg)
	if err != nil {
		return nil, nil, err
	}

	if err := parseSuppressions(cfg); err != nil {
		return nil, nil, err
	}

	return cfg, syscalls, nil
}

func parseSyscalls(cfg *Config) (map[int]bool, error) {
	match := func(call *sys.Call, str string) bool {
		if str == call.CallName || str == call.Name {
			return true
		}
		if len(str) > 1 && str[len(str)-1] == '*' && strings.HasPrefix(call.Name, str[:len(str)-1]) {
			return true
		}
		return false
	}

	syscalls := make(map[int]bool)
	if len(cfg.Enable_Syscalls) != 0 {
		for _, c := range cfg.Enable_Syscalls {
			n := 0
			for _, call := range sys.Calls {
				if match(call, c) {
					syscalls[call.ID] = true
					n++
				}
			}
			if n == 0 {
				return nil, fmt.Errorf("unknown enabled syscall: %v", c)
			}
		}
	} else {
		for _, call := range sys.Calls {
			syscalls[call.ID] = true
		}
	}
	for _, c := range cfg.Disable_Syscalls {
		n := 0
		for _, call := range sys.Calls {
			if match(call, c) {
				delete(syscalls, call.ID)
				n++
			}
		}
		if n == 0 {
			return nil, fmt.Errorf("unknown disabled syscall: %v", c)
		}
	}
	// mmap is used to allocate memory.
	syscalls[sys.CallMap["mmap"].ID] = true

	return syscalls, nil
}

func parseSuppressions(cfg *Config) error {
	// Add some builtin suppressions.
	supp := append(cfg.Suppressions, []string{
		"panic: failed to start executor binary",
		"panic: executor failed: pthread_create failed",
		"panic: failed to create temp dir",
		"fatal error: runtime: out of memory",
		"fatal error: runtime: cannot allocate memory",
		"fatal error: unexpected signal during runtime execution", // presubmably OOM turned into SIGBUS
		"Out of memory: Kill process .* \\(syz-fuzzer\\)",
		"lowmemorykiller: Killing 'syz-fuzzer'",
		//"INFO: lockdep is turned off", // printed by some sysrq that dumps scheduler state, but also on all lockdep reports
	}...)
	for _, s := range supp {
		re, err := regexp.Compile(s)
		if err != nil {
			return fmt.Errorf("failed to compile suppression '%v': %v", s, err)
		}
		cfg.ParsedSuppressions = append(cfg.ParsedSuppressions, re)
	}
	for _, ignore := range cfg.Ignores {
		re, err := regexp.Compile(ignore)
		if err != nil {
			return fmt.Errorf("failed to compile ignore '%v': %v", ignore, err)
		}
		cfg.ParsedIgnores = append(cfg.ParsedIgnores, re)
	}
	return nil
}

func CreateVMConfig(cfg *Config, index int) (*vm.Config, error) {
	if index < 0 || index >= cfg.Count {
		return nil, fmt.Errorf("invalid VM index %v (count %v)", index, cfg.Count)
	}
	workdir, err := fileutil.ProcessTempDir(cfg.Workdir)
	if err != nil {
		return nil, fmt.Errorf("failed to create instance temp dir: %v", err)
	}
	vmCfg := &vm.Config{
		Name:        fmt.Sprintf("%v-%v-%v", cfg.Type, cfg.Name, index),
		Index:       index,
		Workdir:     workdir,
		Bin:         cfg.Bin,
		BinArgs:     cfg.Bin_Args,
		Kernel:      cfg.Kernel,
		Cmdline:     cfg.Cmdline,
		Image:       cfg.Image,
		Initrd:      cfg.Initrd,
		Sshkey:      cfg.Sshkey,
		Executor:    filepath.Join(cfg.Syzkaller, "bin", "syz-executor"),
		Cpu:         cfg.Cpu,
		Mem:         cfg.Mem,
		Debug:       cfg.Debug,
		MachineType: cfg.Machine_Type,
	}
	if len(cfg.Devices) != 0 {
		vmCfg.Device = cfg.Devices[index]
	}
	return vmCfg, nil
}

func checkUnknownFields(data []byte) (string, error) {
	// While https://github.com/golang/go/issues/15314 is not resolved
	// we don't have a better way than to enumerate all known fields.
	var fields = []string{
		"Name",
		"Http",
		"Rpc",
		"Workdir",
		"Vmlinux",
		"Kernel",
		"Tag",
		"Cmdline",
		"Image",
		"Cpu",
		"Mem",
		"Sshkey",
		"Bin",
		"Bin_Args",
		"Debug",
		"Output",
		"Hub_Addr",
		"Hub_Key",
		"Syzkaller",
		"Type",
		"Count",
		"Devices",
		"Procs",
		"Cover",
		"Reproduce",
		"Sandbox",
		"Leak",
		"Enable_Syscalls",
		"Disable_Syscalls",
		"Suppressions",
		"Ignores",
		"Initrd",
		"Machine_Type",
	}
	f := make(map[string]interface{})
	if err := json.Unmarshal(data, &f); err != nil {
		return "", fmt.Errorf("failed to parse config file: %v", err)
	}
	for k := range f {
		ok := false
		for _, k1 := range fields {
			if strings.ToLower(k) == strings.ToLower(k1) {
				ok = true
				break
			}
		}
		if !ok {
			return k, nil
		}
	}
	return "", nil
}
<commit_msg>config: allow relative paths in configs<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package config

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/google/syzkaller/fileutil"
	"github.com/google/syzkaller/sys"
	"github.com/google/syzkaller/vm"
)

type Config struct {
	Name     string // Instance name (used for identification and as GCE instance prefix)
	Http     string // TCP address to serve HTTP stats page (e.g. "localhost:50000")
	Rpc      string // TCP address to serve RPC for fuzzer processes (optional, only useful for type "none")
	Workdir  string
	Vmlinux  string
	Kernel   string // e.g. arch/x86/boot/bzImage
	Tag      string // arbitrary optional tag that is saved along with crash reports (e.g. kernel branch/commit)
	Cmdline  string // kernel command line
	Image    string // linux image for VMs
	Initrd   string // linux initial ramdisk. (optional)
	Cpu      int    // number of VM CPUs
	Mem      int    // amount of VM memory in MBs
	Sshkey   string // root ssh key for the image
	Bin      string // qemu/lkvm binary name
	Bin_Args string // additional command line arguments for qemu/lkvm binary
	Debug    bool   // dump all VM output to console
	Output   string // one of stdout/dmesg/file (useful only for local VM)

	Hub_Addr string
	Hub_Key  string

	Syzkaller string   // path to syzkaller checkout (syz-manager will look for binaries in bin subdir)
	Type      string   // VM type (qemu, kvm, local)
	Count     int      // number of VMs (don't secify for adb, instead specify devices)
	Devices   []string // device IDs for adb
	Procs     int      // number of parallel processes inside of every VM

	Sandbox string // type of sandbox to use during fuzzing:
	// "none": don't do anything special (has false positives, e.g. due to killing init)
	// "setuid": impersonate into user nobody (65534), default
	// "namespace": create a new namespace for fuzzer using CLONE_NEWNS/CLONE_NEWNET/CLONE_NEWPID/etc,
	//	requires building kernel with CONFIG_NAMESPACES, CONFIG_UTS_NS, CONFIG_USER_NS, CONFIG_PID_NS and CONFIG_NET_NS.

	Machine_Type string // GCE machine type (e.g. "n1-highcpu-2")

	Cover     bool // use kcov coverage (default: true)
	Leak      bool // do memory leak checking
	Reproduce bool // reproduce, localize and minimize crashers (on by default)

	Enable_Syscalls  []string
	Disable_Syscalls []string
	Suppressions     []string // don't save reports matching these regexps, but reboot VM after them
	Ignores          []string // completely ignore reports matching these regexps (don't save nor reboot)

	// Implementation details beyond this point.
	ParsedSuppressions []*regexp.Regexp `json:"-"`
	ParsedIgnores      []*regexp.Regexp `json:"-"`
}

func Parse(filename string) (*Config, map[int]bool, error) {
	if filename == "" {
		return nil, nil, fmt.Errorf("supply config in -config flag")
	}
	data, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to read config file: %v", err)
	}
	return parse(data)
}

func parse(data []byte) (*Config, map[int]bool, error) {
	unknown, err := checkUnknownFields(data)
	if err != nil {
		return nil, nil, err
	}
	if unknown != "" {
		return nil, nil, fmt.Errorf("unknown field '%v' in config", unknown)
	}
	cfg := new(Config)
	cfg.Cover = true
	cfg.Reproduce = true
	cfg.Sandbox = "setuid"
	if err := json.Unmarshal(data, cfg); err != nil {
		return nil, nil, fmt.Errorf("failed to parse config file: %v", err)
	}
	if _, err := os.Stat(filepath.Join(cfg.Syzkaller, "bin/syz-fuzzer")); err != nil {
		return nil, nil, fmt.Errorf("bad config syzkaller param: can't find bin/syz-fuzzer")
	}
	if _, err := os.Stat(filepath.Join(cfg.Syzkaller, "bin/syz-executor")); err != nil {
		return nil, nil, fmt.Errorf("bad config syzkaller param: can't find bin/syz-executor")
	}
	if cfg.Http == "" {
		return nil, nil, fmt.Errorf("config param http is empty")
	}
	if cfg.Workdir == "" {
		return nil, nil, fmt.Errorf("config param workdir is empty")
	}
	if cfg.Vmlinux == "" {
		return nil, nil, fmt.Errorf("config param vmlinux is empty")
	}
	if cfg.Type == "" {
		return nil, nil, fmt.Errorf("config param type is empty")
	}
	switch cfg.Type {
	case "none":
		if cfg.Count != 0 {
			return nil, nil, fmt.Errorf("invalid config param count: %v, type \"none\" does not support param count", cfg.Count)
		}
		if cfg.Rpc == "" {
			return nil, nil, fmt.Errorf("config param rpc is empty (required for type \"none\")")
		}
		if len(cfg.Devices) != 0 {
			return nil, nil, fmt.Errorf("type %v does not support devices param", cfg.Type)
		}
	case "adb":
		if cfg.Count != 0 {
			return nil, nil, fmt.Errorf("don't specify count for adb, instead specify devices")
		}
		if len(cfg.Devices) == 0 {
			return nil, nil, fmt.Errorf("specify at least 1 adb device")
		}
		cfg.Count = len(cfg.Devices)
	case "gce":
		if cfg.Machine_Type == "" {
			return nil, nil, fmt.Errorf("machine_type parameter is empty (required for gce)")
		}
		fallthrough
	default:
		if cfg.Count <= 0 || cfg.Count > 1000 {
			return nil, nil, fmt.Errorf("invalid config param count: %v, want (1, 1000]", cfg.Count)
		}
		if len(cfg.Devices) != 0 {
			return nil, nil, fmt.Errorf("type %v does not support devices param", cfg.Type)
		}
	}
	if cfg.Rpc == "" {
		cfg.Rpc = "localhost:0"
	}
	if cfg.Procs <= 0 {
		cfg.Procs = 1
	}
	if cfg.Procs > 32 {
		return nil, nil, fmt.Errorf("config param procs has higher value '%v' then the max supported 32", cfg.Procs)
	}
	if cfg.Output == "" {
		if cfg.Type == "local" {
			cfg.Output = "none"
		} else {
			cfg.Output = "stdout"
		}
	}
	switch cfg.Output {
	case "none", "stdout", "dmesg", "file":
	default:
		return nil, nil, fmt.Errorf("config param output must contain one of none/stdout/dmesg/file")
	}
	switch cfg.Sandbox {
	case "none", "setuid", "namespace":
	default:
		return nil, nil, fmt.Errorf("config param sandbox must contain one of none/setuid/namespace")
	}

	wd, err := os.Getwd()
	if err != nil {
		return nil, nil, fmt.Errorf("failed to get wd: %v", err)
	}
	abs := func(path string) string {
		if path != "" && !filepath.IsAbs(path) {
			path = filepath.Join(wd, path)
		}
		return path
	}
	if cfg.Image != "9p" {
		cfg.Image = abs(cfg.Image)
	}
	cfg.Workdir = abs(cfg.Workdir)
	cfg.Kernel = abs(cfg.Kernel)
	cfg.Vmlinux = abs(cfg.Vmlinux)
	cfg.Syzkaller = abs(cfg.Syzkaller)
	cfg.Initrd = abs(cfg.Initrd)
	cfg.Sshkey = abs(cfg.Sshkey)
	cfg.Bin = abs(cfg.Bin)

	syscalls, err := parseSyscalls(cfg)
	if err != nil {
		return nil, nil, err
	}

	if err := parseSuppressions(cfg); err != nil {
		return nil, nil, err
	}

	return cfg, syscalls, nil
}

func parseSyscalls(cfg *Config) (map[int]bool, error) {
	match := func(call *sys.Call, str string) bool {
		if str == call.CallName || str == call.Name {
			return true
		}
		if len(str) > 1 && str[len(str)-1] == '*' && strings.HasPrefix(call.Name, str[:len(str)-1]) {
			return true
		}
		return false
	}

	syscalls := make(map[int]bool)
	if len(cfg.Enable_Syscalls) != 0 {
		for _, c := range cfg.Enable_Syscalls {
			n := 0
			for _, call := range sys.Calls {
				if match(call, c) {
					syscalls[call.ID] = true
					n++
				}
			}
			if n == 0 {
				return nil, fmt.Errorf("unknown enabled syscall: %v", c)
			}
		}
	} else {
		for _, call := range sys.Calls {
			syscalls[call.ID] = true
		}
	}
	for _, c := range cfg.Disable_Syscalls {
		n := 0
		for _, call := range sys.Calls {
			if match(call, c) {
				delete(syscalls, call.ID)
				n++
			}
		}
		if n == 0 {
			return nil, fmt.Errorf("unknown disabled syscall: %v", c)
		}
	}
	// mmap is used to allocate memory.
	syscalls[sys.CallMap["mmap"].ID] = true

	return syscalls, nil
}

func parseSuppressions(cfg *Config) error {
	// Add some builtin suppressions.
	supp := append(cfg.Suppressions, []string{
		"panic: failed to start executor binary",
		"panic: executor failed: pthread_create failed",
		"panic: failed to create temp dir",
		"fatal error: runtime: out of memory",
		"fatal error: runtime: cannot allocate memory",
		"fatal error: unexpected signal during runtime execution", // presubmably OOM turned into SIGBUS
		"Out of memory: Kill process .* \\(syz-fuzzer\\)",
		"lowmemorykiller: Killing 'syz-fuzzer'",
		//"INFO: lockdep is turned off", // printed by some sysrq that dumps scheduler state, but also on all lockdep reports
	}...)
	for _, s := range supp {
		re, err := regexp.Compile(s)
		if err != nil {
			return fmt.Errorf("failed to compile suppression '%v': %v", s, err)
		}
		cfg.ParsedSuppressions = append(cfg.ParsedSuppressions, re)
	}
	for _, ignore := range cfg.Ignores {
		re, err := regexp.Compile(ignore)
		if err != nil {
			return fmt.Errorf("failed to compile ignore '%v': %v", ignore, err)
		}
		cfg.ParsedIgnores = append(cfg.ParsedIgnores, re)
	}
	return nil
}

func CreateVMConfig(cfg *Config, index int) (*vm.Config, error) {
	if index < 0 || index >= cfg.Count {
		return nil, fmt.Errorf("invalid VM index %v (count %v)", index, cfg.Count)
	}
	workdir, err := fileutil.ProcessTempDir(cfg.Workdir)
	if err != nil {
		return nil, fmt.Errorf("failed to create instance temp dir: %v", err)
	}
	vmCfg := &vm.Config{
		Name:        fmt.Sprintf("%v-%v-%v", cfg.Type, cfg.Name, index),
		Index:       index,
		Workdir:     workdir,
		Bin:         cfg.Bin,
		BinArgs:     cfg.Bin_Args,
		Kernel:      cfg.Kernel,
		Cmdline:     cfg.Cmdline,
		Image:       cfg.Image,
		Initrd:      cfg.Initrd,
		Sshkey:      cfg.Sshkey,
		Executor:    filepath.Join(cfg.Syzkaller, "bin", "syz-executor"),
		Cpu:         cfg.Cpu,
		Mem:         cfg.Mem,
		Debug:       cfg.Debug,
		MachineType: cfg.Machine_Type,
	}
	if len(cfg.Devices) != 0 {
		vmCfg.Device = cfg.Devices[index]
	}
	return vmCfg, nil
}

func checkUnknownFields(data []byte) (string, error) {
	// While https://github.com/golang/go/issues/15314 is not resolved
	// we don't have a better way than to enumerate all known fields.
	var fields = []string{
		"Name",
		"Http",
		"Rpc",
		"Workdir",
		"Vmlinux",
		"Kernel",
		"Tag",
		"Cmdline",
		"Image",
		"Cpu",
		"Mem",
		"Sshkey",
		"Bin",
		"Bin_Args",
		"Debug",
		"Output",
		"Hub_Addr",
		"Hub_Key",
		"Syzkaller",
		"Type",
		"Count",
		"Devices",
		"Procs",
		"Cover",
		"Reproduce",
		"Sandbox",
		"Leak",
		"Enable_Syscalls",
		"Disable_Syscalls",
		"Suppressions",
		"Ignores",
		"Initrd",
		"Machine_Type",
	}
	f := make(map[string]interface{})
	if err := json.Unmarshal(data, &f); err != nil {
		return "", fmt.Errorf("failed to parse config file: %v", err)
	}
	for k := range f {
		ok := false
		for _, k1 := range fields {
			if strings.ToLower(k) == strings.ToLower(k1) {
				ok = true
				break
			}
		}
		if !ok {
			return k, nil
		}
	}
	return "", nil
}
<|endoftext|>


<commit_before>package config

import (
	"io/ioutil"
	"net/url"
	"os"
	"strings"

	"github.com/pkg/errors"

	"code.cloudfoundry.org/bytefmt"

	yaml "gopkg.in/yaml.v2"
)

type Config struct {
	Buildpacks BlobstoreConfig
	Droplets   BlobstoreConfig
	Packages   BlobstoreConfig
	AppStash   BlobstoreConfig `yaml:"app_stash"`

	// BuildpackCache is a Pseudo blobstore, because in reality it is using the Droplets blobstore.
	// However, we want to be able to control its max_body_size.
	BuildpackCache BlobstoreConfig `yaml:"buildpack_cache"`

	Logging         LoggingConfig
	PublicEndpoint  string `yaml:"public_endpoint"`
	PrivateEndpoint string `yaml:"private_endpoint"`
	Secret          string
	Port            int
	SigningUsers    []Credential `yaml:"signing_users"`
	MaxBodySize     string       `yaml:"max_body_size"`
	CertFile        string       `yaml:"cert_file"`
	KeyFile         string       `yaml:"key_file"`

	CCUpdater *CCUpdaterConfig `yaml:"cc_updater"`
}

func (config *Config) PublicEndpointUrl() *url.URL {
	u, e := url.Parse(config.PublicEndpoint)
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
	return u
}

func (config *Config) PrivateEndpointUrl() *url.URL {
	u, e := url.Parse(config.PrivateEndpoint)
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
	return u
}

type BlobstoreConfig struct {
	BlobstoreType     string                    `yaml:"blobstore_type"`
	LocalConfig       *LocalBlobstoreConfig     `yaml:"local_config"`
	S3Config          *S3BlobstoreConfig        `yaml:"s3_config"`
	GCPConfig         *GCPBlobstoreConfig       `yaml:"gcp_config"`
	AzureConfig       *AzureBlobstoreConfig     `yaml:"azure_config"`
	OpenstackConfig   *OpenstackBlobstoreConfig `yaml:"openstack_config"`
	WebdavConfig      *WebdavBlobstoreConfig    `yaml:"webdav_config"`
	MaxBodySize       string                    `yaml:"max_body_size"`
	GlobalMaxBodySize string                    // Not to be set by yaml
}

func (config *BlobstoreConfig) MaxBodySizeBytes() uint64 {
	if config.MaxBodySize == "" {
		if config.GlobalMaxBodySize == "" {
			return 0
		}
		bytes, e := bytefmt.ToBytes(config.GlobalMaxBodySize)
		if e != nil {
			panic("Unexpected error: " + e.Error())
		}
		return bytes
	}
	bytes, e := bytefmt.ToBytes(config.MaxBodySize)
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
	return bytes
}

type LocalBlobstoreConfig struct {
	PathPrefix string `yaml:"path_prefix"`
}

type S3BlobstoreConfig struct {
	Bucket          string
	AccessKeyID     string `yaml:"access_key_id"`
	SecretAccessKey string `yaml:"secret_access_key"`
	Region          string
	Host            string
}

type GCPBlobstoreConfig struct {
	Bucket       string
	PrivateKeyID string `yaml:"private_key_id"`
	PrivateKey   string `yaml:"private_key"`
	Email        string
	TokenURL     string `yaml:"token_url"`
}

type AzureBlobstoreConfig struct {
	ContainerName string `yaml:"container_name"`
	AccountName   string `yaml:"account_name"`
	AccountKey    string `yaml:"account_key"`
}

type OpenstackBlobstoreConfig struct {
	ContainerName  string `yaml:"container_name"`
	DomainName     string `yaml:"domain_name"`
	DomainId       string `yaml:"domain_id"`
	Username       string
	ApiKey         string `yaml:"api_key"`
	AuthURL        string `yaml:"auth_url"`
	Region         string
	AuthVersion    int    `yaml:"auth_version"`
	Internal       bool   // Set this to true to use the the internal / service network
	Tenant         string // Name of the tenant (v2,v3 auth only)
	TenantId       string `yaml:"tenant_id"`        // Id of the tenant (v2,v3 auth only)
	EndpointType   string `yaml:"endpoint_type"`    // Endpoint type (v2,v3 auth only) (default is public URL unless Internal is set)
	TenantDomain   string `yaml:"tenant_domain"`    // Name of the tenant's domain (v3 auth only), only needed if it differs from the user domain
	TenantDomainId string `yaml:"tenant_domain_id"` // Id of the tenant's domain (v3 auth only), only needed if it differs the from user domain
	TrustId        string `yaml:"trust_id"`         // Id of the trust (v3 auth only)

	AccountMetaTempURLKey string `yaml:"account_meta_temp_url_key"` // used as secret for signed URLs
}

type WebdavBlobstoreConfig struct {
	PrivateEndpoint string `yaml:"private_endpoint"`
	PublicEndpoint  string `yaml:"public_endpoint"`
	CACertPath      string `yaml:"ca_cert_path"`
	SkipCertVerify  bool   `yaml:"skip_cert_verify"`
	Username        string
	Password        string
}

func (config WebdavBlobstoreConfig) CACert() string {
	caCert, e := ioutil.ReadFile(config.CACertPath)
	if e != nil {
		panic(errors.Wrapf(e, "Error while reading CA cert file \"%v\"", config.CACertPath))
	}
	return string(caCert)
}

type Credential struct {
	Username string
	Password string
}

type LoggingConfig struct {
	Level string
}

type CCUpdaterConfig struct {
	Endpoint       string
	Method         string
	ClientCertFile string `yaml:"client_cert_file"`
	ClientKeyFile  string `yaml:"client_key_file"`
	CACertFile     string `yaml:"ca_cert_file"`
}

func LoadConfig(filename string) (config Config, err error) {
	file, e := os.Open(filename)
	if e != nil {
		return Config{}, errors.New("error opening config. Caused by: " + e.Error())
	}
	defer file.Close()
	content, e := ioutil.ReadAll(file)
	if e != nil {
		return Config{}, errors.New("error reading config. Caused by: " + e.Error())
	}
	e = yaml.Unmarshal(content, &config)
	if e != nil {
		return Config{}, errors.New("error parsing config. Caused by: " + e.Error())
	}
	config.Droplets.GlobalMaxBodySize = config.MaxBodySize
	config.Packages.GlobalMaxBodySize = config.MaxBodySize
	config.AppStash.GlobalMaxBodySize = config.MaxBodySize
	config.Buildpacks.GlobalMaxBodySize = config.MaxBodySize
	config.BuildpackCache.GlobalMaxBodySize = config.MaxBodySize

	var errs []string

	if config.BuildpackCache.AzureConfig != nil ||
		config.BuildpackCache.GCPConfig != nil ||
		config.BuildpackCache.LocalConfig != nil ||
		config.BuildpackCache.OpenstackConfig != nil ||
		config.BuildpackCache.S3Config != nil ||
		config.BuildpackCache.WebdavConfig != nil {
		errs = append(errs, "buildpack_cache must not have a blobstore configured, as it only exists to allow to configure max_body_size. "+
			"As blobstore, the droplet blobstore is used.")
	}
	if config.Port == 0 {
		errs = append(errs, "port must be an integer > 0")
	}
	if config.PublicEndpoint == "" {
		errs = append(errs, "public_endpoint must not be empty")
	} else {
		publicEndpoint, e := url.Parse(config.PublicEndpoint)
		if e != nil {
			errs = append(errs, "public_endpoint is invalid. Caused by:"+e.Error())
		} else {
			if publicEndpoint.Host == "" {
				errs = append(errs, "public_endpoint host must not be empty")
			}
			if publicEndpoint.Scheme != "https" {
				errs = append(errs, "public_endpoint must use https://")
			}
		}
	}
	if config.PrivateEndpoint == "" {
		errs = append(errs, "private_endpoint must not be empty")
	} else {
		privateEndpoint, e := url.Parse(config.PrivateEndpoint)
		if e != nil {
			errs = append(errs, "private_endpoint is invalid. Caused by:"+e.Error())
		} else {
			if privateEndpoint.Host == "" {
				errs = append(errs, "private_endpoint host must not be empty")
			}
			if privateEndpoint.Scheme != "https" {
				errs = append(errs, "private_endpoint must use https://")
			}
		}
	}
	if config.CertFile == "" {
		errs = append(errs, "cert_file must not be empty")
	}
	if config.KeyFile == "" {
		errs = append(errs, "key_file must not be empty")
	}
	if config.MaxBodySize != "" {
		_, e = bytefmt.ToBytes(config.MaxBodySize)
		if e != nil {
			errs = append(errs, "max_body_size is invalid. Caused by: "+e.Error())
		}
	}

	if config.CCUpdater != nil {
		config.CCUpdater.Method = "PATCH"
		u, e := url.Parse(config.CCUpdater.Endpoint)
		if e != nil {
			errs = append(errs, "cc_updater.endpoint is invalid. Caused by:"+e.Error())
		} else if u.Host == "" {
			errs = append(errs, "cc_updater.endpoint host must not be empty")
		}
	}

	// TODO validate CACertsPaths
	if len(errs) > 0 {
		return Config{}, errors.New("error in config values: " + strings.Join(errs, "; "))
	}
	return
}
<commit_msg>Fix config unmarshalling<commit_after>package config

import (
	"io/ioutil"
	"net/url"
	"os"
	"strings"

	"github.com/pkg/errors"

	"code.cloudfoundry.org/bytefmt"

	yaml "gopkg.in/yaml.v2"
)

type Config struct {
	Buildpacks BlobstoreConfig
	Droplets   BlobstoreConfig
	Packages   BlobstoreConfig
	AppStash   BlobstoreConfig `yaml:"app_stash"`

	// BuildpackCache is a Pseudo blobstore, because in reality it is using the Droplets blobstore.
	// However, we want to be able to control its max_body_size.
	BuildpackCache BlobstoreConfig `yaml:"buildpack_cache"`

	Logging         LoggingConfig
	PublicEndpoint  string `yaml:"public_endpoint"`
	PrivateEndpoint string `yaml:"private_endpoint"`
	Secret          string
	Port            int
	SigningUsers    []Credential `yaml:"signing_users"`
	MaxBodySize     string       `yaml:"max_body_size"`
	CertFile        string       `yaml:"cert_file"`
	KeyFile         string       `yaml:"key_file"`

	CCUpdater *CCUpdaterConfig `yaml:"cc_updater"`
}

func (config *Config) PublicEndpointUrl() *url.URL {
	u, e := url.Parse(config.PublicEndpoint)
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
	return u
}

func (config *Config) PrivateEndpointUrl() *url.URL {
	u, e := url.Parse(config.PrivateEndpoint)
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
	return u
}

type BlobstoreConfig struct {
	BlobstoreType     string                    `yaml:"blobstore_type"`
	LocalConfig       *LocalBlobstoreConfig     `yaml:"local_config"`
	S3Config          *S3BlobstoreConfig        `yaml:"s3_config"`
	GCPConfig         *GCPBlobstoreConfig       `yaml:"gcp_config"`
	AzureConfig       *AzureBlobstoreConfig     `yaml:"azure_config"`
	OpenstackConfig   *OpenstackBlobstoreConfig `yaml:"openstack_config"`
	WebdavConfig      *WebdavBlobstoreConfig    `yaml:"webdav_config"`
	MaxBodySize       string                    `yaml:"max_body_size"`
	GlobalMaxBodySize string                    // Not to be set by yaml
}

func (config *BlobstoreConfig) MaxBodySizeBytes() uint64 {
	if config.MaxBodySize == "" {
		if config.GlobalMaxBodySize == "" {
			return 0
		}
		bytes, e := bytefmt.ToBytes(config.GlobalMaxBodySize)
		if e != nil {
			panic("Unexpected error: " + e.Error())
		}
		return bytes
	}
	bytes, e := bytefmt.ToBytes(config.MaxBodySize)
	if e != nil {
		panic("Unexpected error: " + e.Error())
	}
	return bytes
}

type LocalBlobstoreConfig struct {
	PathPrefix string `yaml:"path_prefix"`
}

type S3BlobstoreConfig struct {
	Bucket          string
	AccessKeyID     string `yaml:"access_key_id"`
	SecretAccessKey string `yaml:"secret_access_key"`
	Region          string
	Host            string `yaml:",omitempty"`
}

type GCPBlobstoreConfig struct {
	Bucket       string
	PrivateKeyID string `yaml:"private_key_id"`
	PrivateKey   string `yaml:"private_key"`
	Email        string
	TokenURL     string `yaml:"token_url"`
}

type AzureBlobstoreConfig struct {
	ContainerName string `yaml:"container_name"`
	AccountName   string `yaml:"account_name"`
	AccountKey    string `yaml:"account_key"`
}

type OpenstackBlobstoreConfig struct {
	ContainerName  string `yaml:"container_name"`
	DomainName     string `yaml:"domain_name"`
	DomainId       string `yaml:"domain_id"`
	Username       string
	ApiKey         string `yaml:"api_key"`
	AuthURL        string `yaml:"auth_url"`
	Region         string
	AuthVersion    int    `yaml:"auth_version"`
	Internal       bool   // Set this to true to use the the internal / service network
	Tenant         string // Name of the tenant (v2,v3 auth only)
	TenantId       string `yaml:"tenant_id"`        // Id of the tenant (v2,v3 auth only)
	EndpointType   string `yaml:"endpoint_type"`    // Endpoint type (v2,v3 auth only) (default is public URL unless Internal is set)
	TenantDomain   string `yaml:"tenant_domain"`    // Name of the tenant's domain (v3 auth only), only needed if it differs from the user domain
	TenantDomainId string `yaml:"tenant_domain_id"` // Id of the tenant's domain (v3 auth only), only needed if it differs the from user domain
	TrustId        string `yaml:"trust_id"`         // Id of the trust (v3 auth only)

	AccountMetaTempURLKey string `yaml:"account_meta_temp_url_key"` // used as secret for signed URLs
}

type WebdavBlobstoreConfig struct {
	PrivateEndpoint string `yaml:"private_endpoint"`
	PublicEndpoint  string `yaml:"public_endpoint"`
	CACertPath      string `yaml:"ca_cert_path"`
	SkipCertVerify  bool   `yaml:"skip_cert_verify"`
	Username        string
	Password        string
}

func (config WebdavBlobstoreConfig) CACert() string {
	caCert, e := ioutil.ReadFile(config.CACertPath)
	if e != nil {
		panic(errors.Wrapf(e, "Error while reading CA cert file \"%v\"", config.CACertPath))
	}
	return string(caCert)
}

type Credential struct {
	Username string
	Password string
}

type LoggingConfig struct {
	Level string
}

type CCUpdaterConfig struct {
	Endpoint       string
	Method         string
	ClientCertFile string `yaml:"client_cert_file"`
	ClientKeyFile  string `yaml:"client_key_file"`
	CACertFile     string `yaml:"ca_cert_file"`
}

func LoadConfig(filename string) (config Config, err error) {
	file, e := os.Open(filename)
	if e != nil {
		return Config{}, errors.New("error opening config. Caused by: " + e.Error())
	}
	defer file.Close()
	content, e := ioutil.ReadAll(file)
	if e != nil {
		return Config{}, errors.New("error reading config. Caused by: " + e.Error())
	}
	e = yaml.Unmarshal(content, &config)
	if e != nil {
		return Config{}, errors.New("error parsing config. Caused by: " + e.Error())
	}
	config.Droplets.GlobalMaxBodySize = config.MaxBodySize
	config.Packages.GlobalMaxBodySize = config.MaxBodySize
	config.AppStash.GlobalMaxBodySize = config.MaxBodySize
	config.Buildpacks.GlobalMaxBodySize = config.MaxBodySize
	config.BuildpackCache.GlobalMaxBodySize = config.MaxBodySize

	var errs []string

	if config.BuildpackCache.AzureConfig != nil ||
		config.BuildpackCache.GCPConfig != nil ||
		config.BuildpackCache.LocalConfig != nil ||
		config.BuildpackCache.OpenstackConfig != nil ||
		config.BuildpackCache.S3Config != nil ||
		config.BuildpackCache.WebdavConfig != nil {
		errs = append(errs, "buildpack_cache must not have a blobstore configured, as it only exists to allow to configure max_body_size. "+
			"As blobstore, the droplet blobstore is used.")
	}
	if config.Port == 0 {
		errs = append(errs, "port must be an integer > 0")
	}
	if config.PublicEndpoint == "" {
		errs = append(errs, "public_endpoint must not be empty")
	} else {
		publicEndpoint, e := url.Parse(config.PublicEndpoint)
		if e != nil {
			errs = append(errs, "public_endpoint is invalid. Caused by:"+e.Error())
		} else {
			if publicEndpoint.Host == "" {
				errs = append(errs, "public_endpoint host must not be empty")
			}
			if publicEndpoint.Scheme != "https" {
				errs = append(errs, "public_endpoint must use https://")
			}
		}
	}
	if config.PrivateEndpoint == "" {
		errs = append(errs, "private_endpoint must not be empty")
	} else {
		privateEndpoint, e := url.Parse(config.PrivateEndpoint)
		if e != nil {
			errs = append(errs, "private_endpoint is invalid. Caused by:"+e.Error())
		} else {
			if privateEndpoint.Host == "" {
				errs = append(errs, "private_endpoint host must not be empty")
			}
			if privateEndpoint.Scheme != "https" {
				errs = append(errs, "private_endpoint must use https://")
			}
		}
	}
	if config.CertFile == "" {
		errs = append(errs, "cert_file must not be empty")
	}
	if config.KeyFile == "" {
		errs = append(errs, "key_file must not be empty")
	}
	if config.MaxBodySize != "" {
		_, e = bytefmt.ToBytes(config.MaxBodySize)
		if e != nil {
			errs = append(errs, "max_body_size is invalid. Caused by: "+e.Error())
		}
	}

	if config.CCUpdater != nil {
		config.CCUpdater.Method = "PATCH"
		u, e := url.Parse(config.CCUpdater.Endpoint)
		if e != nil {
			errs = append(errs, "cc_updater.endpoint is invalid. Caused by:"+e.Error())
		} else if u.Host == "" {
			errs = append(errs, "cc_updater.endpoint host must not be empty")
		}
	}

	// TODO validate CACertsPaths
	if len(errs) > 0 {
		return Config{}, errors.New("error in config values: " + strings.Join(errs, "; "))
	}
	return
}
<|endoftext|>


<commit_before>package config

import (
	"os"
	"path/filepath"
	"strings"

	"github.com/UnnoTed/fileb0x/compression"
	"github.com/UnnoTed/fileb0x/custom"
	"github.com/UnnoTed/fileb0x/updater"
)

// Config holds the json/yaml/toml data
type Config struct {
	Dest        string
	Pkg         string
	Fmt         bool // gofmt
	Compression *compression.Options
	Tags        string

	Output string

	Custom []custom.Custom

	Spread     bool
	Unexported bool
	Clean      bool
	Debug      bool
	Updater    updater.Config
}

// Defaults set the default value for some variables
func (cfg *Config) Defaults() error {
	// default destination
	if cfg.Dest == "" {
		cfg.Dest = "/"
	}

	// insert "/" at end of dest when it's not found
	if !strings.HasSuffix(cfg.Dest, "/") {
		cfg.Dest += "/"
	}

	// default file name
	if cfg.Output == "" {
		cfg.Output = "b0x.go"
	}

	// inserts .go at the end of file name
	if !strings.HasSuffix(cfg.Output, ".go") {
		cfg.Output += ".go"
	}

	// inserts an A before the output file's name so it can
	// run init() before b0xfile's
	if !strings.HasPrefix(cfg.Output, "a") {
		cfg.Output = "a" + cfg.Output
	}

	// default package
	if cfg.Pkg == "" {
		cfg.Pkg = "main"
	}

	// remove b0xfiles when [clean] is true
	// it doesn't clean destination's folders
	if cfg.Clean {
		matches, err := filepath.Glob(cfg.Dest + "b0xfile_*.go")
		if err != nil {
			return err
		}

		// remove matched file
		for _, f := range matches {
			err = os.Remove(f)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
<commit_msg>make sure cfg.Compression is populated<commit_after>package config

import (
	"os"
	"path/filepath"
	"strings"

	"github.com/UnnoTed/fileb0x/compression"
	"github.com/UnnoTed/fileb0x/custom"
	"github.com/UnnoTed/fileb0x/updater"
)

// Config holds the json/yaml/toml data
type Config struct {
	Dest        string
	Pkg         string
	Fmt         bool // gofmt
	Compression *compression.Options
	Tags        string

	Output string

	Custom []custom.Custom

	Spread     bool
	Unexported bool
	Clean      bool
	Debug      bool
	Updater    updater.Config
}

// Defaults set the default value for some variables
func (cfg *Config) Defaults() error {
	// default destination
	if cfg.Dest == "" {
		cfg.Dest = "/"
	}

	// insert "/" at end of dest when it's not found
	if !strings.HasSuffix(cfg.Dest, "/") {
		cfg.Dest += "/"
	}

	// default file name
	if cfg.Output == "" {
		cfg.Output = "b0x.go"
	}

	// inserts .go at the end of file name
	if !strings.HasSuffix(cfg.Output, ".go") {
		cfg.Output += ".go"
	}

	// inserts an A before the output file's name so it can
	// run init() before b0xfile's
	if !strings.HasPrefix(cfg.Output, "a") {
		cfg.Output = "a" + cfg.Output
	}

	// default package
	if cfg.Pkg == "" {
		cfg.Pkg = "main"
	}

	// remove b0xfiles when [clean] is true
	// it doesn't clean destination's folders
	if cfg.Clean {
		matches, err := filepath.Glob(cfg.Dest + "b0xfile_*.go")
		if err != nil {
			return err
		}

		// remove matched file
		for _, f := range matches {
			err = os.Remove(f)
			if err != nil {
				return err
			}
		}
	}

	if cfg.Compression == nil {
		cfg.Compression = &compression.Options{
			Compress: false,
			Method: "DefaultCompression",
			Keep: false,
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package infrastructure

import (
	"database/sql"

	"github.com/GerardSoleCa/PubKeyManager/interfaces"
	_ "github.com/xeodou/go-sqlcipher"
)

type SqliteHandler struct {
	Conn *sql.DB
}

func (handler *SqliteHandler) Execute(statement string, args ...interface{}) (interfaces.Result, error) {
	result, err := handler.Conn.Exec(statement, args...)
	if err != nil {
		return new(SqliteResult), err
	}
	r := new(SqliteResult)
	r.Result = result
	return r, nil
}

func (handler *SqliteHandler) Query(statement string, args ...interface{}) (interfaces.Row, error) {
	rows, err := handler.Conn.Query(statement, args...)
	if err != nil {
		return new(SqliteRow), err
	}
	row := new(SqliteRow)
	row.Rows = rows
	return row, nil
}

type SqliteResult struct {
	Result sql.Result
}

func (r SqliteResult) LastInsertId() (int64, error) {
	return r.Result.LastInsertId()
}

func (r SqliteResult) RowsAffected() (int64, error) {
	return r.Result.RowsAffected()
}

type SqliteRow struct {
	Rows *sql.Rows
}

func (r SqliteRow) Scan(dest ...interface{}) {
	r.Rows.Scan(dest...)
}

func (r SqliteRow) Next() bool {
	return r.Rows.Next()
}
func (r SqliteRow) Close() {
	r.Rows.Close()
}

func NewSqliteHandler(dbfileName string, password string) *SqliteHandler {
	conn, _ := sql.Open("sqlite3", dbfileName)

	p := "PRAGMA key = '" + password + "';"
	_, err := conn.Exec(p)
	if err != nil {
		panic(err)
	}

	sqliteHandler := new(SqliteHandler)
	sqliteHandler.Conn = conn
	return sqliteHandler
}
<commit_msg>Adding last docs<commit_after>package infrastructure

import (
	"database/sql"

	"github.com/GerardSoleCa/PubKeyManager/interfaces"
	// Blank import for go-sqlcipher
	_ "github.com/xeodou/go-sqlcipher"
)

// SqliteHandler struct
type SqliteHandler struct {
	Conn *sql.DB
}

// Execute function contained on SqliteHandler
func (handler *SqliteHandler) Execute(statement string, args ...interface{}) (interfaces.Result, error) {
	result, err := handler.Conn.Exec(statement, args...)
	if err != nil {
		return new(SqliteResult), err
	}
	r := new(SqliteResult)
	r.Result = result
	return r, nil
}

// Query function contained on SqliteHandler
func (handler *SqliteHandler) Query(statement string, args ...interface{}) (interfaces.Row, error) {
	rows, err := handler.Conn.Query(statement, args...)
	if err != nil {
		return new(SqliteRow), err
	}
	row := new(SqliteRow)
	row.Rows = rows
	return row, nil
}

// SqliteResult struct
type SqliteResult struct {
	Result sql.Result
}

// LastInsertId function contained on SqliteResult
func (r SqliteResult) LastInsertId() (int64, error) {
	return r.Result.LastInsertId()
}

// RowsAffected function contained on SqliteResult
func (r SqliteResult) RowsAffected() (int64, error) {
	return r.Result.RowsAffected()
}

// SqliteRow struct
type SqliteRow struct {
	Rows *sql.Rows
}

// Scan function contained on SqliteResult
func (r SqliteRow) Scan(dest ...interface{}) {
	r.Rows.Scan(dest...)
}

// Next function contained on SqliteRow
func (r SqliteRow) Next() bool {
	return r.Rows.Next()
}
// Close function contained on SqliteRow
func (r SqliteRow) Close() {
	r.Rows.Close()
}

// NewSqliteHanlder creates a new Ciphered SqliteHandler
func NewSqliteHandler(dbfileName string, password string) *SqliteHandler {
	conn, _ := sql.Open("sqlite3", dbfileName)

	p := "PRAGMA key = '" + password + "';"
	_, err := conn.Exec(p)
	if err != nil {
		panic(err)
	}

	sqliteHandler := new(SqliteHandler)
	sqliteHandler.Conn = conn
	return sqliteHandler
}
<|endoftext|>


<commit_before>// Copyright 2015 Eleme Inc. All rights reserved.

package config

// Configuration for banshee with default values:
//
//	Global Options
//		debug			if on debug mode. [default: false]
//		interval		incomding metrics time interval (in sec). [default: 10]
//		periodicity		metrics periodicity (in sec), NumTimeSpans x TimeSpan.
//						[default: [480, 180]]
//	SQLite Options
//		file			file path for sqlite, which maintains admin rules etc.
//						[default: "rules.db"]
//	LevelDB Options
//		file			file path for leveldb, which maintains analyzation
//						results. [default: "stats.db"]
//	Detector Options
//		port			detector tcp port to listen. [default: 2015]
//		trendFactor		the factor to calculate trending value via weighted
//						moving average algorithm. [default: 0.07]
//		strict			if this is set false, detector will passivate latest
//						metric. [default: true]
//		whitelist		metrics whitelist, if set empty `[]`, rule patterns
//						from sqlite will be used. [default: ["*"]]
//		blacklist		metrics blacklist, detector will allow one metric to
//						pass only if it matches one pattern in whitelist and
//						dosent match any pattern in blacklist. [default:
//						["statsd.*"]]
//		startSize		detector won't start to detect until the data set is
//						larger than this size. [default: 32]
//	WebApp Options
//		port			webapp http port to listen. [default: 2016]
//		auth			username and password for admin basic auth. [default:
//						["admin", "admin"]]
//	Alerter Options
//		command			shell command to execute on anomalies detected, leaving
//						empty means do nothing. [default: ""]
//
// See also exampleConfig.json please.

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

type Config struct {
	Debug       bool           `json:"debug"`
	Interval    int            `json:"interval"`
	Periodicity [2]int         `json:"periodicity"`
	SQLite      ConfigSQLite   `json:"sqlite"`
	LevelDB     ConfigLevelDB  `json:"leveldb"`
	Detector    ConfigDetector `json:"detector"`
	Webapp      ConfigWebapp   `json:"webapp"`
	Alerter     ConfigAlerter  `json:"alerter"`
}

type ConfigSQLite struct {
	file string `json:"file"`
}

type ConfigLevelDB struct {
	file string `json:"file"`
}

type ConfigDetector struct {
	Port        int      `json:"port"`
	TrendFactor float64  `json:"trendFactor"`
	Strict      bool     `json:"strict"`
	WhiteList   []string `json:"whitelist"`
	BlackList   []string `json:"blackList"`
	StartSize   int      `json:"startSize"`
}

type ConfigWebapp struct {
	Port int       `json:"port"`
	Auth [2]string `json:"auth"`
}

type ConfigAlerter struct {
	Command string `json:"command"`
}

// NewConfigWithDefaults creates a Config with default values.
func NewConfigWithDefaults() *Config {
	config := new(Config)
	config.Debug = false
	config.Interval = 10
	config.Periodicity = [2]int{480, 180}
	config.SQLite.file = "rules.db"
	config.LevelDB.file = "stats.db"
	config.Detector.Port = 2015
	config.Detector.TrendFactor = 0.07
	config.Detector.Strict = true
	config.Detector.WhiteList = []string{"*"}
	config.Detector.BlackList = []string{"statsd.*"}
	config.Detector.StartSize = 32
	config.Webapp.Port = 2016
	config.Webapp.Auth = [2]string{"admin", "admin"}
	config.Alerter.Command = ""
	return config
}

// NewConfigWithJsonBytes creates a Config with json literal bytes.
func NewConfigWithJsonBytes(b []byte) (*Config, error) {
	config := NewConfigWithDefaults()
	err := json.Unmarshal(b, config)
	if err != nil {
		return nil, err
	}
	return config, nil
}

// NewConfigWithJsonFile creates a Config from a json file by fileName.
func NewConfigWithJsonFile(fileName string) (*Config, error) {
	b, err := ioutil.ReadFile(fileName)
	if err != nil {
		return nil, err
	}
	return NewConfigWithJsonBytes(b)
}
<commit_msg>Fix godoc<commit_after>// Copyright 2015 Eleme Inc. All rights reserved.

// Configuration for banshee with default values.
//  Global Options
//    debug            if on debug mode. [default: false]
//    interval         incomding metrics time interval (in sec). [default: 10]
//    periodicity      metrics periodicity (in sec), NumTimeSpans x TimeSpan.
//                     [default: [480, 180]]
//  SQLite Options
//    file             file path for sqlite, which maintains admin rules etc.
//                     [default: "rules.db"]
//  LevelDB Options
//    file             file path for leveldb, which maintains analyzation
//                     results. [default: "stats.db"]
//  Detector Options
//    port             detector tcp port to listen. [default: 2015]
//    trendFactor      the factor to calculate trending value via weighted
//                     moving average algorithm. [default: 0.07]
//    strict           if this is set false, detector will passivate latest
//                     metric. [default: true]
//    whitelist        metrics whitelist, if set empty `[]`, rule patterns from
//                     sqlite will be used. [default: ["*"]]
//    blacklist        metrics blacklist, detector will allow one metric to pass
//                     only if it matches one pattern in whitelist and dosent
//                     match any pattern in blacklist. [default: ["statsd.*"]]
//    startSize        detector won't start to detect until the data set is
//                     larger than this size. [default: 32]
//  WebApp Options
//    port             webapp http port to listen. [default: 2016]
//    auth             username and password for admin basic auth. [default:
//                     ["admin", "admin"]]
//  Alerter Options
//    command          shell command to execute on anomalies detected, leaving
//                     empty means do nothing. [default: ""]
// See also exampleConfig.json please.
//
package config

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

type Config struct {
	Debug       bool           `json:"debug"`
	Interval    int            `json:"interval"`
	Periodicity [2]int         `json:"periodicity"`
	SQLite      ConfigSQLite   `json:"sqlite"`
	LevelDB     ConfigLevelDB  `json:"leveldb"`
	Detector    ConfigDetector `json:"detector"`
	Webapp      ConfigWebapp   `json:"webapp"`
	Alerter     ConfigAlerter  `json:"alerter"`
}

type ConfigSQLite struct {
	file string `json:"file"`
}

type ConfigLevelDB struct {
	file string `json:"file"`
}

type ConfigDetector struct {
	Port        int      `json:"port"`
	TrendFactor float64  `json:"trendFactor"`
	Strict      bool     `json:"strict"`
	WhiteList   []string `json:"whitelist"`
	BlackList   []string `json:"blackList"`
	StartSize   int      `json:"startSize"`
}

type ConfigWebapp struct {
	Port int       `json:"port"`
	Auth [2]string `json:"auth"`
}

type ConfigAlerter struct {
	Command string `json:"command"`
}

// NewConfigWithDefaults creates a Config with default values.
func NewConfigWithDefaults() *Config {
	config := new(Config)
	config.Debug = false
	config.Interval = 10
	config.Periodicity = [2]int{480, 180}
	config.SQLite.file = "rules.db"
	config.LevelDB.file = "stats.db"
	config.Detector.Port = 2015
	config.Detector.TrendFactor = 0.07
	config.Detector.Strict = true
	config.Detector.WhiteList = []string{"*"}
	config.Detector.BlackList = []string{"statsd.*"}
	config.Detector.StartSize = 32
	config.Webapp.Port = 2016
	config.Webapp.Auth = [2]string{"admin", "admin"}
	config.Alerter.Command = ""
	return config
}

// NewConfigWithJsonBytes creates a Config with json literal bytes.
func NewConfigWithJsonBytes(b []byte) (*Config, error) {
	config := NewConfigWithDefaults()
	err := json.Unmarshal(b, config)
	if err != nil {
		return nil, err
	}
	return config, nil
}

// NewConfigWithJsonFile creates a Config from a json file by fileName.
func NewConfigWithJsonFile(fileName string) (*Config, error) {
	b, err := ioutil.ReadFile(fileName)
	if err != nil {
		return nil, err
	}
	return NewConfigWithJsonBytes(b)
}
<|endoftext|>


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

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

var commentPrefix = []string{"//", "#", ";"}

// Config struct constructs a new configuration handler.
type Config struct {
	filename string
	config   map[string]map[string]string
}

// NewConfig function cnstructs a new Config struct with filename. You have to
// call Read() function to let it read from the file. Otherwise you will get
// empty string (i.e., "") when you are calling Get() function. Another usage
// is that you call NewConfig() function and then call Add()/Set() function to
// add new key-values to the configuration. Finally you can call Write()
// function to write the new configuration to the file.
func NewConfig(filename string) *Config {
	c := new(Config)
	c.filename = filename
	c.config = make(map[string]map[string]string)
	return c
}

// Filename function returns the filename of the configuration.
func (c *Config) Filename() string {
	return c.filename
}

// SetFilename function sets the filename of the configuration.
func (c *Config) SetFilename(filename string) {
	c.filename = filename
}

// Reset function reset the map in the configuration.
func (c *Config) Reset() {
	c.config = make(map[string]map[string]string)
}

// Read function reads configurations from the file defined in
// Config.filename.
func (c *Config) Read() error {
	in, err := os.Open(c.filename)
	if err != nil {
		return err
	}
	defer in.Close()
	scanner := bufio.NewScanner(in)
	line := ""
	section := ""
	for scanner.Scan() {
		if scanner.Text() == "" {
			continue
		}
		if line == "" {
			sec, ok := checkSection(scanner.Text())
			if ok {
				section = sec
				continue
			}
		}
		if checkComment(scanner.Text()) {
			continue
		}
		line += scanner.Text()
		if strings.HasSuffix(line, "\\") {
			line = line[:len(line)-1]
			continue
		}
		key, value, ok := checkLine(line)
		if !ok {
			return errors.New("WRONG: " + line)
		}
		c.Set(section, key, value)
		line = ""
	}
	return nil
}

// Get function returns the value of a key in the configuration. If the key
// does not exist, it returns empty string (i.e., "").
func (c *Config) Get(section string, key string) string {
	value, ok := c.config[section][key]
	if !ok {
		return ""
	}
	return value
}

// Set function updates the value of a key in the configuration. Function
// Set() is exactly the same as function Add().
func (c *Config) Set(section string, key string, value string) {
	_, ok := c.config[section]
	if !ok {
		c.config[section] = make(map[string]string)
	}
	c.config[section][key] = value
}

// Add function adds a new key to the configuration. Function Add() is exactly
// the same as function Set().
func (c *Config) Add(section string, key string, value string) {
	c.Set(section, key, value)
}

// Del function deletes a key from the configuration.
func (c *Config) Del(section string, key string) {
	_, ok := c.config[section]
	if ok {
		delete(c.config[section], key)
		if len(c.config[section]) == 0 {
			delete(c.config, section)
		}
	}
}

// Write function writes the updated configuration back.
func (c *Config) Write() error {
	return nil
}

// WriteTo function writes the configuration to a new file. This function
// re-organizes the configuration and deletes all the comments.
func (c *Config) WriteTo(filename string) error {
	content := ""
	for k, v := range c.config {
		content += fmt.Sprintf("[%v]\n", k)
		for key, value := range v {
			content += fmt.Sprintf("\t%v = %v\n", key, value)
		}
	}
	return ioutil.WriteFile(filename, []byte(content), 0644)
}

// To check this line if section or not. If it is not a section, it returns
// "".
func checkSection(line string) (string, bool) {
	line = strings.TrimSpace(line)
	lineLen := len(line)
	if lineLen < 2 {
		return "", false
	}
	if line[0] == '[' && line[lineLen-1] == ']' {
		return line[1 : lineLen-1], true
	}
	return "", false
}

// To check this line is a valid key-value pair or not.
func checkLine(line string) (string, string, bool) {
	key := ""
	value := ""
	sp := strings.SplitN(line, "=", 2)
	if len(sp) != 2 {
		return key, value, false
	}
	key = strings.TrimSpace(sp[0])
	value = strings.TrimSpace(sp[1])
	return key, value, true
}

// To check this line is a whole line comment or not.
func checkComment(line string) bool {
	line = strings.TrimSpace(line)
	for p := range commentPrefix {
		if strings.HasPrefix(line, commentPrefix[p]) {
			return true
		}
	}
	return false
}
<commit_msg>handle global configurations<commit_after>// Copyright 2013, Cong Ding. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// author: Cong Ding <dinggnu@gmail.com>
//
package config

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

var commentPrefix = []string{"//", "#", ";"}

// Config struct constructs a new configuration handler.
type Config struct {
	filename string
	config   map[string]map[string]string
}

// NewConfig function cnstructs a new Config struct with filename. You have to
// call Read() function to let it read from the file. Otherwise you will get
// empty string (i.e., "") when you are calling Get() function. Another usage
// is that you call NewConfig() function and then call Add()/Set() function to
// add new key-values to the configuration. Finally you can call Write()
// function to write the new configuration to the file.
func NewConfig(filename string) *Config {
	c := new(Config)
	c.filename = filename
	c.config = make(map[string]map[string]string)
	return c
}

// Filename function returns the filename of the configuration.
func (c *Config) Filename() string {
	return c.filename
}

// SetFilename function sets the filename of the configuration.
func (c *Config) SetFilename(filename string) {
	c.filename = filename
}

// Reset function reset the map in the configuration.
func (c *Config) Reset() {
	c.config = make(map[string]map[string]string)
}

// Read function reads configurations from the file defined in
// Config.filename.
func (c *Config) Read() error {
	in, err := os.Open(c.filename)
	if err != nil {
		return err
	}
	defer in.Close()
	scanner := bufio.NewScanner(in)
	line := ""
	section := ""
	for scanner.Scan() {
		if scanner.Text() == "" {
			continue
		}
		if line == "" {
			sec, ok := checkSection(scanner.Text())
			if ok {
				section = sec
				continue
			}
		}
		if checkComment(scanner.Text()) {
			continue
		}
		line += scanner.Text()
		if strings.HasSuffix(line, "\\") {
			line = line[:len(line)-1]
			continue
		}
		key, value, ok := checkLine(line)
		if !ok {
			return errors.New("WRONG: " + line)
		}
		c.Set(section, key, value)
		line = ""
	}
	return nil
}

// Get function returns the value of a key in the configuration. If the key
// does not exist, it returns empty string (i.e., "").
func (c *Config) Get(section string, key string) string {
	value, ok := c.config[section][key]
	if !ok {
		return ""
	}
	return value
}

// Set function updates the value of a key in the configuration. Function
// Set() is exactly the same as function Add().
func (c *Config) Set(section string, key string, value string) {
	_, ok := c.config[section]
	if !ok {
		c.config[section] = make(map[string]string)
	}
	c.config[section][key] = value
}

// Add function adds a new key to the configuration. Function Add() is exactly
// the same as function Set().
func (c *Config) Add(section string, key string, value string) {
	c.Set(section, key, value)
}

// Del function deletes a key from the configuration.
func (c *Config) Del(section string, key string) {
	_, ok := c.config[section]
	if ok {
		delete(c.config[section], key)
		if len(c.config[section]) == 0 {
			delete(c.config, section)
		}
	}
}

// Write function writes the updated configuration back.
func (c *Config) Write() error {
	return nil
}

// WriteTo function writes the configuration to a new file. This function
// re-organizes the configuration and deletes all the comments.
func (c *Config) WriteTo(filename string) error {
	content := ""
	for k, v := range c.config {
		if k != "" {
			content += fmt.Sprintf("[%v]\n", k)
		}
		for key, value := range v {
			if k != "" {
				content += fmt.Sprintf("\t%v = %v\n", key, value)
			} else {
				content += fmt.Sprintf("%v = %v\n", key, value)
			}
		}
	}
	return ioutil.WriteFile(filename, []byte(content), 0644)
}

// To check this line if section or not. If it is not a section, it returns
// "".
func checkSection(line string) (string, bool) {
	line = strings.TrimSpace(line)
	lineLen := len(line)
	if lineLen < 2 {
		return "", false
	}
	if line[0] == '[' && line[lineLen-1] == ']' {
		return line[1 : lineLen-1], true
	}
	return "", false
}

// To check this line is a valid key-value pair or not.
func checkLine(line string) (string, string, bool) {
	key := ""
	value := ""
	sp := strings.SplitN(line, "=", 2)
	if len(sp) != 2 {
		return key, value, false
	}
	key = strings.TrimSpace(sp[0])
	value = strings.TrimSpace(sp[1])
	return key, value, true
}

// To check this line is a whole line comment or not.
func checkComment(line string) bool {
	line = strings.TrimSpace(line)
	for p := range commentPrefix {
		if strings.HasPrefix(line, commentPrefix[p]) {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>/*
Package config helps creating configuration structs.

The intended usage would be a simple struct that calls Value() on
a fields initialization. E.g.

	var portProperty   = config.NewEnvProperty("PORT", "8080")
	// If the $DOMAIN env variable not set the configuration creation will fail with a fatal error
	var domainProperty = config.NewRequiredEnvProperty("DOMAIN")

	type Config struct {
		Port   string
		Domain string
	}

	func NewConfig() Config {
		return Config{
			Port:   portProperty.Value(),
			Domain: domainProperty.Value(),
		}
	}
*/
package config

import (
	"log"
	"os"
)

// Property can be used to fetch default values for configuration properties.
type Property interface {
	Value() string
}

// NewRequiredEnvProperty returns a Property that gets its value from
// the specified environment variable. Panics if the variable is not set.
func NewRequiredEnvProperty(envVariableName string) Property {
	return requiredEnvProperty{
		envVariableName: envVariableName,
	}
}

// NewEnvProperty returns a Property that gets its value from the
// specified environment variable. If the environment vatiable is not set
// the fallback value will be used instead
func NewEnvProperty(envVariableName string, fallbackValue string) Property {
	return envProperty{
		envVariableName: envVariableName,
		fallbackValue:   fallbackValue,
	}
}

type envProperty struct {
	envVariableName string
	fallbackValue   string
}

func (prop envProperty) Value() (defaultValue string) {
	defaultValue = os.Getenv(prop.envVariableName)
	if defaultValue == "" {
		defaultValue = prop.fallbackValue
	}
	return
}

type requiredEnvProperty struct {
	envVariableName string
}

func (prop requiredEnvProperty) Value() (defaultValue string) {
	defaultValue = os.Getenv(prop.envVariableName)
	if defaultValue == "" {
		log.Fatalf("Please set the %s environment variable", prop.envVariableName)
	}
	return
}
<commit_msg>move config package to a separate repo<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"time"

	"github.com/codegangsta/cli"
	"github.com/kardianos/osext"
)

var InitialPath string
var InitialGoPath string

var Verbose bool

var SpinnerCharSet = 14
var SpinnerInterval = 50 * time.Millisecond

func main() {
	currentExecutable, _ := osext.Executable()
	vendoredBunchPath, err := path.Join(".vendor", "bin", "bunch")

	fi1, errStat1 := os.Stat(currentExecutable)
	fi2, errStat2 := os.Stat(vendoredBunchPath)

	if exists, _ := pathExists(vendoredBunchPath); err == nil && errStat1 == nil && errStat2 == nil && exists && os.SameFile(fi1, fi2) {
		cmd := exec.Command(vendoredBunchPath, os.Args[1:]...)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		err = cmd.Run()
		if err != nil {
			fmt.Println("running vendored bin/bunch was unsuccessful")
			os.Exit(1)
		} else {
			if cmd.ProcessState.Success() {
				os.Exit(0)
			} else {
				os.Exit(1)
			}
		}
	}

	InitialPath = os.Getenv("PATH")
	InitialGoPath = os.Getenv("GOPATH")

	app := cli.NewApp()
	app.Name = "bunch"
	app.Usage = "npm-like tool for managing Go dependencies"
	app.Version = "0.0.1"
	app.Authors = []cli.Author{cli.Author{Name: "Daniil Kulchenko", Email: "daniil@kulchenko.com"}}

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "output more information",
		},
	}

	app.Before = func(context *cli.Context) error {
		Verbose = context.GlobalBool("verbose")

		return nil
	}

	app.Commands = []cli.Command{
		{
			Name:    "install",
			Aliases: []string{"i"},
			Usage:   "install package(s)",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "save",
					Usage: "save installed package to Bunchfile",
				},
				cli.BoolFlag{
					Name:  "g",
					Usage: "install package to global $GOPATH instead of vendored directory",
				},
			},
			Action: func(c *cli.Context) {
				installCommand(c, false, true)
			},
		},
		{
			Name:    "update",
			Aliases: []string{"u"},
			Usage:   "update package(s)",
			Action: func(c *cli.Context) {
				installCommand(c, true, true)
			},
		},
		{
			Name:    "uninstall",
			Aliases: []string{"r"},
			Usage:   "uninstall package(s)",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "save",
					Usage: "save uninstalled package to Bunchfile",
				},
				cli.BoolFlag{
					Name:  "g",
					Usage: "uninstall package from global $GOPATH instead of vendored directory",
				},
			},
			Action: func(c *cli.Context) {
				uninstallCommand(c)
			},
		},
		{
			Name:  "prune",
			Usage: "remove packages not referenced in Bunchfile",
			Action: func(c *cli.Context) {
				pruneCommand(c)
			},
		},
		{
			Name:  "outdated",
			Usage: "list outdated packages",
			Action: func(c *cli.Context) {
				outdatedCommand(c)
			},
		},
		{
			Name:  "lock",
			Usage: "generate a file locking down current versions of dependencies",
			Action: func(c *cli.Context) {
				lockCommand(c)
			},
		},
		{
			Name:  "rebuild",
			Usage: "rebuild all dependencies",
			Action: func(c *cli.Context) {
				installCommand(c, true, false)
			},
		},
		{
			Name:  "generate",
			Usage: "generate a Bunchfile based on package imports in current directory",
			Action: func(c *cli.Context) {
				generateCommand(c)
			},
		},
		{
			Name:            "go",
			Usage:           "run a Go command within the vendor environment (e.g. bunch go fmt)",
			SkipFlagParsing: true,
			Action: func(c *cli.Context) {
				goCommand(c)
			},
		},
		{
			Name:            "exec",
			Usage:           "run any command within the vendor environment (e.g. bunch exec make)",
			SkipFlagParsing: true,
			Action: func(c *cli.Context) {
				execCommand(c)
			},
		},
		{
			Name:            "shell",
			Usage:           "start a shell within the vendor environment",
			SkipFlagParsing: true,
			Action: func(c *cli.Context) {
				shellCommand(c)
			},
		},
		{
			Name:  "shim",
			Usage: "sourced in .bash_profile to alias the 'go' tool",
			Action: func(c *cli.Context) {
				shimCommand(c)
			},
		},
	}

	app.Run(os.Args)
}
<commit_msg>syntax fixes<commit_after>package main

import (
	"fmt"
	"os"
	"os/exec"
	"path"
	"time"

	"github.com/codegangsta/cli"
	"github.com/kardianos/osext"
)

var InitialPath string
var InitialGoPath string

var Verbose bool

var SpinnerCharSet = 14
var SpinnerInterval = 50 * time.Millisecond

func main() {
	currentExecutable, _ := osext.Executable()
	vendoredBunchPath := path.Join(".vendor", "bin", "bunch")

	fi1, errStat1 := os.Stat(currentExecutable)
	fi2, errStat2 := os.Stat(vendoredBunchPath)

	if exists, _ := pathExists(vendoredBunchPath); errStat1 == nil && errStat2 == nil && exists && os.SameFile(fi1, fi2) {
		cmd := exec.Command(vendoredBunchPath, os.Args[1:]...)
		cmd.Stdin = os.Stdin
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		err := cmd.Run()
		if err != nil {
			fmt.Println("running vendored bin/bunch was unsuccessful")
			os.Exit(1)
		} else {
			if cmd.ProcessState.Success() {
				os.Exit(0)
			} else {
				os.Exit(1)
			}
		}
	}

	InitialPath = os.Getenv("PATH")
	InitialGoPath = os.Getenv("GOPATH")

	app := cli.NewApp()
	app.Name = "bunch"
	app.Usage = "npm-like tool for managing Go dependencies"
	app.Version = "0.0.1"
	app.Authors = []cli.Author{cli.Author{Name: "Daniil Kulchenko", Email: "daniil@kulchenko.com"}}

	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "output more information",
		},
	}

	app.Before = func(context *cli.Context) error {
		Verbose = context.GlobalBool("verbose")

		return nil
	}

	app.Commands = []cli.Command{
		{
			Name:    "install",
			Aliases: []string{"i"},
			Usage:   "install package(s)",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "save",
					Usage: "save installed package to Bunchfile",
				},
				cli.BoolFlag{
					Name:  "g",
					Usage: "install package to global $GOPATH instead of vendored directory",
				},
			},
			Action: func(c *cli.Context) {
				installCommand(c, false, true)
			},
		},
		{
			Name:    "update",
			Aliases: []string{"u"},
			Usage:   "update package(s)",
			Action: func(c *cli.Context) {
				installCommand(c, true, true)
			},
		},
		{
			Name:    "uninstall",
			Aliases: []string{"r"},
			Usage:   "uninstall package(s)",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "save",
					Usage: "save uninstalled package to Bunchfile",
				},
				cli.BoolFlag{
					Name:  "g",
					Usage: "uninstall package from global $GOPATH instead of vendored directory",
				},
			},
			Action: func(c *cli.Context) {
				uninstallCommand(c)
			},
		},
		{
			Name:  "prune",
			Usage: "remove packages not referenced in Bunchfile",
			Action: func(c *cli.Context) {
				pruneCommand(c)
			},
		},
		{
			Name:  "outdated",
			Usage: "list outdated packages",
			Action: func(c *cli.Context) {
				outdatedCommand(c)
			},
		},
		{
			Name:  "lock",
			Usage: "generate a file locking down current versions of dependencies",
			Action: func(c *cli.Context) {
				lockCommand(c)
			},
		},
		{
			Name:  "rebuild",
			Usage: "rebuild all dependencies",
			Action: func(c *cli.Context) {
				installCommand(c, true, false)
			},
		},
		{
			Name:  "generate",
			Usage: "generate a Bunchfile based on package imports in current directory",
			Action: func(c *cli.Context) {
				generateCommand(c)
			},
		},
		{
			Name:            "go",
			Usage:           "run a Go command within the vendor environment (e.g. bunch go fmt)",
			SkipFlagParsing: true,
			Action: func(c *cli.Context) {
				goCommand(c)
			},
		},
		{
			Name:            "exec",
			Usage:           "run any command within the vendor environment (e.g. bunch exec make)",
			SkipFlagParsing: true,
			Action: func(c *cli.Context) {
				execCommand(c)
			},
		},
		{
			Name:            "shell",
			Usage:           "start a shell within the vendor environment",
			SkipFlagParsing: true,
			Action: func(c *cli.Context) {
				shellCommand(c)
			},
		},
		{
			Name:  "shim",
			Usage: "sourced in .bash_profile to alias the 'go' tool",
			Action: func(c *cli.Context) {
				shimCommand(c)
			},
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package terraform

// ResourceProvider is an interface that must be implemented by any
// resource provider: the thing that creates and manages the resources in
// a Terraform configuration.
//
// Important implementation note: All returned pointers, such as
// *ResourceConfig, *InstanceState, *InstanceDiff, etc. must not point to
// shared data. Terraform is highly parallel and assumes that this data is safe
// to read/write in parallel so it must be unique references. Note that it is
// safe to return arguments as results, however.
type ResourceProvider interface {
	/*********************************************************************
	* Functions related to the provider
	*********************************************************************/

	// Input is called to ask the provider to ask the user for input
	// for completing the configuration if necesarry.
	//
	// This may or may not be called, so resource provider writers shouldn't
	// rely on this being available to set some default values for validate
	// later. Example of a situation where this wouldn't be called is if
	// the user is not using a TTY.
	Input(UIInput, *ResourceConfig) (*ResourceConfig, error)

	// Validate is called once at the beginning with the raw configuration
	// (no interpolation done) and can return a list of warnings and/or
	// errors.
	//
	// This is called once with the provider configuration only. It may not
	// be called at all if no provider configuration is given.
	//
	// This should not assume that any values of the configurations are valid.
	// The primary use case of this call is to check that required keys are
	// set.
	Validate(*ResourceConfig) ([]string, []error)

	// Configure configures the provider itself with the configuration
	// given. This is useful for setting things like access keys.
	//
	// This won't be called at all if no provider configuration is given.
	//
	// Configure returns an error if it occurred.
	Configure(*ResourceConfig) error

	// Resources returns all the available resource types that this provider
	// knows how to manage.
	Resources() []ResourceType

	// Stop is called when the provider should halt any in-flight actions.
	//
	// This can be used to make a nicer Ctrl-C experience for Terraform.
	// Even if this isn't implemented to do anything (just returns nil),
	// Terraform will still cleanly stop after the currently executing
	// graph node is complete. However, this API can be used to make more
	// efficient halts.
	//
	// Stop doesn't have to and shouldn't block waiting for in-flight actions
	// to complete. It should take any action it wants and return immediately
	// acknowledging it has received the stop request. Terraform core will
	// automatically not make any further API calls to the provider soon
	// after Stop is called (technically exactly once the currently executing
	// graph nodes are complete).
	//
	// The error returned, if non-nil, is assumed to mean that signaling the
	// stop somehow failed and that the user should expect potentially waiting
	// a longer period of time.
	Stop() error

	/*********************************************************************
	* Functions related to individual resources
	*********************************************************************/

	// ValidateResource is called once at the beginning with the raw
	// configuration (no interpolation done) and can return a list of warnings
	// and/or errors.
	//
	// This is called once per resource.
	//
	// This should not assume any of the values in the resource configuration
	// are valid since it is possible they have to be interpolated still.
	// The primary use case of this call is to check that the required keys
	// are set and that the general structure is correct.
	ValidateResource(string, *ResourceConfig) ([]string, []error)

	// Apply applies a diff to a specific resource and returns the new
	// resource state along with an error.
	//
	// If the resource state given has an empty ID, then a new resource
	// is expected to be created.
	Apply(
		*InstanceInfo,
		*InstanceState,
		*InstanceDiff) (*InstanceState, error)

	// Diff diffs a resource versus a desired state and returns
	// a diff.
	Diff(
		*InstanceInfo,
		*InstanceState,
		*ResourceConfig) (*InstanceDiff, error)

	// Refresh refreshes a resource and updates all of its attributes
	// with the latest information.
	Refresh(*InstanceInfo, *InstanceState) (*InstanceState, error)

	/*********************************************************************
	* Functions related to importing
	*********************************************************************/

	// ImportState requests that the given resource be imported.
	//
	// The returned InstanceState only requires ID be set. Importing
	// will always call Refresh after the state to complete it.
	//
	// IMPORTANT: InstanceState doesn't have the resource type attached
	// to it. A type must be specified on the state via the Ephemeral
	// field on the state.
	//
	// This function can return multiple states. Normally, an import
	// will map 1:1 to a physical resource. However, some resources map
	// to multiple. For example, an AWS security group may contain many rules.
	// Each rule is represented by a separate resource in Terraform,
	// therefore multiple states are returned.
	ImportState(*InstanceInfo, string) ([]*InstanceState, error)

	/*********************************************************************
	* Functions related to data resources
	*********************************************************************/

	// ValidateDataSource is called once at the beginning with the raw
	// configuration (no interpolation done) and can return a list of warnings
	// and/or errors.
	//
	// This is called once per data source instance.
	//
	// This should not assume any of the values in the resource configuration
	// are valid since it is possible they have to be interpolated still.
	// The primary use case of this call is to check that the required keys
	// are set and that the general structure is correct.
	ValidateDataSource(string, *ResourceConfig) ([]string, []error)

	// DataSources returns all of the available data sources that this
	// provider implements.
	DataSources() []DataSource

	// ReadDataDiff produces a diff that represents the state that will
	// be produced when the given data source is read using a later call
	// to ReadDataApply.
	ReadDataDiff(*InstanceInfo, *ResourceConfig) (*InstanceDiff, error)

	// ReadDataApply initializes a data instance using the configuration
	// in a diff produced by ReadDataDiff.
	ReadDataApply(*InstanceInfo, *InstanceDiff) (*InstanceState, error)
}

// ResourceProviderCloser is an interface that providers that can close
// connections that aren't needed anymore must implement.
type ResourceProviderCloser interface {
	Close() error
}

// ResourceType is a type of resource that a resource provider can manage.
type ResourceType struct {
	Name       string // Name of the resource, example "instance" (no provider prefix)
	Importable bool   // Whether this resource supports importing
}

// DataSource is a data source that a resource provider implements.
type DataSource struct {
	Name string
}

// ResourceProviderFactory is a function type that creates a new instance
// of a resource provider.
type ResourceProviderFactory func() (ResourceProvider, error)

// ResourceProviderFactoryFixed is a helper that creates a
// ResourceProviderFactory that just returns some fixed provider.
func ResourceProviderFactoryFixed(p ResourceProvider) ResourceProviderFactory {
	return func() (ResourceProvider, error) {
		return p, nil
	}
}

func ProviderHasResource(p ResourceProvider, n string) bool {
	for _, rt := range p.Resources() {
		if rt.Name == n {
			return true
		}
	}

	return false
}

func ProviderHasDataSource(p ResourceProvider, n string) bool {
	for _, rt := range p.DataSources() {
		if rt.Name == n {
			return true
		}
	}

	return false
}
<commit_msg>core: ResourceProviderResolver interface<commit_after>package terraform

import (
	"fmt"

	"github.com/hashicorp/terraform/plugin/discovery"
)

// ResourceProvider is an interface that must be implemented by any
// resource provider: the thing that creates and manages the resources in
// a Terraform configuration.
//
// Important implementation note: All returned pointers, such as
// *ResourceConfig, *InstanceState, *InstanceDiff, etc. must not point to
// shared data. Terraform is highly parallel and assumes that this data is safe
// to read/write in parallel so it must be unique references. Note that it is
// safe to return arguments as results, however.
type ResourceProvider interface {
	/*********************************************************************
	* Functions related to the provider
	*********************************************************************/

	// Input is called to ask the provider to ask the user for input
	// for completing the configuration if necesarry.
	//
	// This may or may not be called, so resource provider writers shouldn't
	// rely on this being available to set some default values for validate
	// later. Example of a situation where this wouldn't be called is if
	// the user is not using a TTY.
	Input(UIInput, *ResourceConfig) (*ResourceConfig, error)

	// Validate is called once at the beginning with the raw configuration
	// (no interpolation done) and can return a list of warnings and/or
	// errors.
	//
	// This is called once with the provider configuration only. It may not
	// be called at all if no provider configuration is given.
	//
	// This should not assume that any values of the configurations are valid.
	// The primary use case of this call is to check that required keys are
	// set.
	Validate(*ResourceConfig) ([]string, []error)

	// Configure configures the provider itself with the configuration
	// given. This is useful for setting things like access keys.
	//
	// This won't be called at all if no provider configuration is given.
	//
	// Configure returns an error if it occurred.
	Configure(*ResourceConfig) error

	// Resources returns all the available resource types that this provider
	// knows how to manage.
	Resources() []ResourceType

	// Stop is called when the provider should halt any in-flight actions.
	//
	// This can be used to make a nicer Ctrl-C experience for Terraform.
	// Even if this isn't implemented to do anything (just returns nil),
	// Terraform will still cleanly stop after the currently executing
	// graph node is complete. However, this API can be used to make more
	// efficient halts.
	//
	// Stop doesn't have to and shouldn't block waiting for in-flight actions
	// to complete. It should take any action it wants and return immediately
	// acknowledging it has received the stop request. Terraform core will
	// automatically not make any further API calls to the provider soon
	// after Stop is called (technically exactly once the currently executing
	// graph nodes are complete).
	//
	// The error returned, if non-nil, is assumed to mean that signaling the
	// stop somehow failed and that the user should expect potentially waiting
	// a longer period of time.
	Stop() error

	/*********************************************************************
	* Functions related to individual resources
	*********************************************************************/

	// ValidateResource is called once at the beginning with the raw
	// configuration (no interpolation done) and can return a list of warnings
	// and/or errors.
	//
	// This is called once per resource.
	//
	// This should not assume any of the values in the resource configuration
	// are valid since it is possible they have to be interpolated still.
	// The primary use case of this call is to check that the required keys
	// are set and that the general structure is correct.
	ValidateResource(string, *ResourceConfig) ([]string, []error)

	// Apply applies a diff to a specific resource and returns the new
	// resource state along with an error.
	//
	// If the resource state given has an empty ID, then a new resource
	// is expected to be created.
	Apply(
		*InstanceInfo,
		*InstanceState,
		*InstanceDiff) (*InstanceState, error)

	// Diff diffs a resource versus a desired state and returns
	// a diff.
	Diff(
		*InstanceInfo,
		*InstanceState,
		*ResourceConfig) (*InstanceDiff, error)

	// Refresh refreshes a resource and updates all of its attributes
	// with the latest information.
	Refresh(*InstanceInfo, *InstanceState) (*InstanceState, error)

	/*********************************************************************
	* Functions related to importing
	*********************************************************************/

	// ImportState requests that the given resource be imported.
	//
	// The returned InstanceState only requires ID be set. Importing
	// will always call Refresh after the state to complete it.
	//
	// IMPORTANT: InstanceState doesn't have the resource type attached
	// to it. A type must be specified on the state via the Ephemeral
	// field on the state.
	//
	// This function can return multiple states. Normally, an import
	// will map 1:1 to a physical resource. However, some resources map
	// to multiple. For example, an AWS security group may contain many rules.
	// Each rule is represented by a separate resource in Terraform,
	// therefore multiple states are returned.
	ImportState(*InstanceInfo, string) ([]*InstanceState, error)

	/*********************************************************************
	* Functions related to data resources
	*********************************************************************/

	// ValidateDataSource is called once at the beginning with the raw
	// configuration (no interpolation done) and can return a list of warnings
	// and/or errors.
	//
	// This is called once per data source instance.
	//
	// This should not assume any of the values in the resource configuration
	// are valid since it is possible they have to be interpolated still.
	// The primary use case of this call is to check that the required keys
	// are set and that the general structure is correct.
	ValidateDataSource(string, *ResourceConfig) ([]string, []error)

	// DataSources returns all of the available data sources that this
	// provider implements.
	DataSources() []DataSource

	// ReadDataDiff produces a diff that represents the state that will
	// be produced when the given data source is read using a later call
	// to ReadDataApply.
	ReadDataDiff(*InstanceInfo, *ResourceConfig) (*InstanceDiff, error)

	// ReadDataApply initializes a data instance using the configuration
	// in a diff produced by ReadDataDiff.
	ReadDataApply(*InstanceInfo, *InstanceDiff) (*InstanceState, error)
}

// ResourceProviderCloser is an interface that providers that can close
// connections that aren't needed anymore must implement.
type ResourceProviderCloser interface {
	Close() error
}

// ResourceType is a type of resource that a resource provider can manage.
type ResourceType struct {
	Name       string // Name of the resource, example "instance" (no provider prefix)
	Importable bool   // Whether this resource supports importing
}

// DataSource is a data source that a resource provider implements.
type DataSource struct {
	Name string
}

// ResourceProviderResolver is an interface implemented by objects that are
// able to resolve a given set of resource provider version constraints
// into ResourceProviderFactory callbacks.
type ResourceProviderResolver interface {
	// Given a constraint map, return a ResourceProviderFactory for each
	// requested provider. If some or all of the constraints cannot be
	// satisfied, return a non-nil slice of errors describing the problems.
	ResolveProviders(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error)
}

// ResourceProviderResolverFunc wraps a callback function and turns it into
// a ResourceProviderResolver implementation, for convenience in situations
// where a function and its associated closure are sufficient as a resolver
// implementation.
type ResourceProviderResolverFunc func(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error)

// ResolveProviders implements ResourceProviderResolver by calling the
// wrapped function.
func (f ResourceProviderResolverFunc) ResolveProviders(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error) {
	return f(reqd)
}

// ResourceProviderResolverFixed returns a ResourceProviderResolver that
// has a fixed set of provider factories provided by the caller. The returned
// resolver ignores version constraints entirely and just returns the given
// factory for each requested provider name.
//
// This function is primarily used in tests, to provide mock providers or
// in-process providers under test.
func ResourceProviderResolverFixed(factories map[string]ResourceProviderFactory) ResourceProviderResolver {
	return ResourceProviderResolverFunc(func(reqd discovery.PluginRequirements) (map[string]ResourceProviderFactory, []error) {
		ret := make(map[string]ResourceProviderFactory, len(reqd))
		var errs []error
		for name := range reqd {
			if factory, exists := factories[name]; exists {
				ret[name] = factory
			} else {
				errs = append(errs, fmt.Errorf("provider %q is not available", name))
			}
		}
		return ret, errs
	})
}

// ResourceProviderFactory is a function type that creates a new instance
// of a resource provider.
type ResourceProviderFactory func() (ResourceProvider, error)

// ResourceProviderFactoryFixed is a helper that creates a
// ResourceProviderFactory that just returns some fixed provider.
func ResourceProviderFactoryFixed(p ResourceProvider) ResourceProviderFactory {
	return func() (ResourceProvider, error) {
		return p, nil
	}
}

func ProviderHasResource(p ResourceProvider, n string) bool {
	for _, rt := range p.Resources() {
		if rt.Name == n {
			return true
		}
	}

	return false
}

func ProviderHasDataSource(p ResourceProvider, n string) bool {
	for _, rt := range p.DataSources() {
		if rt.Name == n {
			return true
		}
	}

	return false
}
<|endoftext|>


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

package mathext

import (
	"math"
	"testing"
)

func TestZeta(t *testing.T) {
	for i, test := range []struct {
		x, q, want float64
	}{
		// Results computed using scipy.special.zeta
		{1, 1, math.Inf(1)},
		{10, 0.5, 1024.0174503557578},
		{5, 2.5, 0.013073166646113805},
		{1.5, 2, 1.6123753486854886},
		{1.5, 20, 0.45287361712938717},
		{2.5, 0.5, 6.2471106345688137},
		{10, 7.5, 2.5578265694201971e-9},
		{12, 2.5, 1.7089167198843551e-5},
		{20, 0.75, 315.3368689825316},
		{25, 0.25, 1125899906842624.0},
	} {
		if got := Zeta(test.x, test.q); math.Abs(got-test.want) > 1e-10 {
			t.Errorf("test %d Zeta(%g, %g) failed: got %g want %g", i, test.x, test.q, got, test.want)
		}
	}
}
<commit_msg>Adding more zeta tests<commit_after>// Copyright ©2016 The gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package mathext

import (
	"math"
	"testing"
)

func TestZeta(t *testing.T) {
	for i, test := range []struct {
		x, q, want float64
	}{
		// Results computed using scipy.special.zeta
		{1, 1, math.Inf(1)},
		{1.00001, 0.5, 100001.96352290553},
		{1.0001, 25, 9996.8017690244506},
		{1.001, 1, 1000.5772884760117},
		{1.01, 10, 97.773405639173305},
		{1.5, 2, 1.6123753486854886},
		{1.5, 20, 0.45287361712938717},
		{2, -0.7, 14.28618087263834},
		{2.5, 0.5, 6.2471106345688137},
		{5, 2.5, 0.013073166646113805},
		{7.5, 5, 7.9463377443314306e-06},
		{10, -0.5, 2048.0174503557578},
		{10, 0.5, 1024.0174503557578},
		{10, 7.5, 2.5578265694201971e-9},
		{12, 2.5, 1.7089167198843551e-5},
		{17, 0.5, 131072.00101513157},
		{20, -2.5, 2097152.0006014798},
		{20, 0.75, 315.3368689825316},
		{25, 0.25, 1125899906842624.0},
		{30, 1, 1.0000000009313275},
	} {
		if got := Zeta(test.x, test.q); math.Abs(got-test.want) > 1e-10 {
			t.Errorf("test %d Zeta(%g, %g) failed: got %g want %g", i, test.x, test.q, got, test.want)
		}
	}
}
<|endoftext|>