<commit_before>package gogl

import "sync"

// VertexSet uses maps to express a value-less (empty struct), indexed unordered list
type VertexSet map[Vertex]struct{}
type adjacencyList map[Vertex]VertexSet

type AdjacencyList struct {
	adjacencyList
	size uint
	mu   sync.RWMutex
}

// Composite literal to create a new AdjacencyList.
func NewAdjacencyList() *AdjacencyList {
	return &AdjacencyList{
		adjacencyList: make(map[Vertex]VertexSet)}
}

func (g AdjacencyList) EachVertex(f func(vertex Vertex)) {
	g.mu.RLock()

	for v := range g.adjacencyList {
		f(v)
	}

	g.mu.RUnlock()
}

func (g AdjacencyList) EachEdge(f func(edge Edge)) {
	g.mu.RLock()

	for source, adjacent := range g.adjacencyList {
		for _, target := range adjacent {
			f(Edge{u: source, v: target})
		}
	}
}

func (g AdjacencyList) EachAdjacent(vertex Vertex, f func(target Vertex)) {
	g.mu.RLock()

	if _, exists := g.adjacencyList[vertex]; exists {
		for _, adjacent := range g.adjacencyList[vertex] {
			f(adjacent)
		}
	}

	g.mu.RUnlock()
}

func (g AdjacencyList) HasVertex(vertex Vertex) (exists bool) {
	g.mu.RLock()
	_, exists = g.adjacencyList[vertex]
	g.mu.RUnlock()
	return
}

func (g AdjacencyList) Order() uint {
	return uint(len(g.adjacencyList))
}

func (g AdjacencyList) Size() uint {
	return g.size
}

func (g AdjacencyList) AddVertex(vertex Vertex) (success bool) {
	g.mu.Lock()

	if exists := g.HasVertex(vertex); !exists {
		// TODO experiment with different lengths...possibly by analyzing existing density?
		g.adjacencyList[vertex] = make(VertexSet, 10)
		success = true
	}

	g.mu.Unlock()
	return
}

func (g AdjacencyList) RemoveVertex(vertex Vertex) (success bool) {
	g.mu.Lock()
	if g.HasVertex(vertex) {
		// TODO Is the expensive search good to do here and now...
		// while read-locked?
		delete(g.adjacencyList, vertex)

		// TODO consider chunking the list and parallelizing into goroutines
		for _, adjacent := range g.adjacencyList {
			if _, has := adjacent[vertex]; has {
				delete(adjacent, vertex)
				g.size--
			}
		}
	}

	g.mu.Unlock()
	return
}
<commit_msg>Implement AddEdge and RemoveEdge.<commit_after>package gogl

import "sync"

// VertexSet uses maps to express a value-less (empty struct), indexed unordered list
type VertexSet map[Vertex]struct{}
type adjacencyList map[Vertex]VertexSet

type AdjacencyList struct {
	adjacencyList
	size uint
	mu   sync.RWMutex
}

// Composite literal to create a new AdjacencyList.
func NewAdjacencyList() *AdjacencyList {
	return &AdjacencyList{
		adjacencyList: make(map[Vertex]VertexSet)}
}

func (g AdjacencyList) EachVertex(f func(vertex Vertex)) {
	g.mu.RLock()

	for v := range g.adjacencyList {
		f(v)
	}

	g.mu.RUnlock()
}

func (g AdjacencyList) EachEdge(f func(edge Edge)) {
	g.mu.RLock()

	for source, adjacent := range g.adjacencyList {
		for _, target := range adjacent {
			f(Edge{u: source, v: target})
		}
	}
}

func (g AdjacencyList) EachAdjacent(vertex Vertex, f func(target Vertex)) {
	g.mu.RLock()

	if _, exists := g.adjacencyList[vertex]; exists {
		for _, adjacent := range g.adjacencyList[vertex] {
			f(adjacent)
		}
	}

	g.mu.RUnlock()
}

func (g AdjacencyList) HasVertex(vertex Vertex) (exists bool) {
	g.mu.RLock()
	_, exists = g.adjacencyList[vertex]
	g.mu.RUnlock()
	return
}

func (g AdjacencyList) Order() uint {
	return uint(len(g.adjacencyList))
}

func (g AdjacencyList) Size() uint {
	return g.size
}

func (g AdjacencyList) AddVertex(vertex Vertex) (success bool) {
	g.mu.Lock()

	if exists := g.HasVertex(vertex); !exists {
		// TODO experiment with different lengths...possibly by analyzing existing density?
		g.adjacencyList[vertex] = make(VertexSet, 10)
		success = true
	}

	g.mu.Unlock()
	return
}

func (g AdjacencyList) RemoveVertex(vertex Vertex) (success bool) {
	g.mu.Lock()
	if g.HasVertex(vertex) {
		// TODO Is the expensive search good to do here and now...
		// while read-locked?
		delete(g.adjacencyList, vertex)

		// TODO consider chunking the list and parallelizing into goroutines
		for _, adjacent := range g.adjacencyList {
			if _, has := adjacent[vertex]; has {
				delete(adjacent, vertex)
				g.size--
			}
		}
	}

	g.mu.Unlock()
	return
}

func (g AdjacencyList) AddEdge(edge Edge) {
	g.mu.Lock()

	g.AddVertex(edge.Source())
	g.AddVertex(edge.Target())

	g.adjacencyList[edge.Source()][edge.Target()] = nil

	g.mu.Unlock()
}

func (g AdjacencyList) RemoveEdge(edge Edge) {
	g.mu.Lock()

	delete(g.adjacencyList, edge.Source())

	g.mu.Unlock()
}
<|endoftext|>


<commit_before>package service

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

	"github.com/juju/errors"

	"github.com/juju/juju/service/common"
	"github.com/juju/juju/version"
)

var jujuVersion = version.Current

// DiscoverService returns an interface to a service apropriate
// for the current system
func DiscoverService(name string, conf common.Conf) (Service, error) {
	initName, err := discoverLocalInitSystem()
	if errors.IsNotFound(err) {
		// Fall back to checking the juju version.
		versionInitName, ok := VersionInitSystem(jujuVersion)
		if !ok {
			return nil, errors.Annotate(err, "nor on local host")
		}
		initName = versionInitName
	} else if err != nil {
		return nil, errors.Trace(err)
	}

	service, err := NewService(name, conf, initName)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return service, nil
}

// VersionInitSystem returns an init system name based on the provided
// version info. If one cannot be identified then false if returned
// for the second return value.
func VersionInitSystem(vers version.Binary) (string, bool) {
	switch vers.OS {
	case version.Windows:
		return InitSystemWindows, true
	case version.Ubuntu:
		switch vers.Series {
		case "precise", "quantal", "raring", "saucy", "trusty", "utopic":
			return InitSystemUpstart, true
		case "":
			return "", false
		default:
			// Check for pre-precise releases.
			os, _ := version.GetOSFromSeries(vers.Series)
			if os == version.Unknown {
				return "", false
			}
			// vivid and later
			return InitSystemSystemd, true
		}
		// TODO(ericsnow) Support other OSes, like version.CentOS.
	default:
		return "", false
	}
}

const pid1 = "/proc/1/cmdline"

type initSystem struct {
	executable string
	name       string
}

var linuxExecutables = []initSystem{
	// Note that some systems link /sbin/init to whatever init system
	// is supported, so in the future we may need some other way to
	// identify upstart uniquely.
	{"/sbin/init", InitSystemUpstart},
	{"/sbin/upstart", InitSystemUpstart},
	{"/sbin/systemd", InitSystemSystemd},
	{"/bin/systemd", InitSystemSystemd},
	{"/lib/systemd/systemd", InitSystemSystemd},
}

func identifyInitSystem(executable string) (string, bool) {
	for _, initSystem := range linuxExecutables {
		if executable == initSystem.executable {
			return initSystem.name, true
		}
	}
	return "", false
}

var runtimeOS = runtime.GOOS
var pid1File = pid1

func discoverLocalInitSystem() (string, error) {
	if runtimeOS == "windows" {
		return InitSystemWindows, nil
	}

	data, err := ioutil.ReadFile(pid1File)
	if os.IsNotExist(err) {
		return "", errors.NotFoundf("init system")
	}
	if err != nil {
		return "", errors.Trace(err)
	}
	out := strings.Trim(strings.TrimSpace(string(data)), "\x00")
	executable := strings.Fields(out)[0]

	initName, ok := identifyInitSystem(executable)
	if !ok {
		return "", errors.NotFoundf("init system (based on %q)", executable)
	}
	logger.Debugf("discovered init system %q from executable %q", initName, executable)
	return initName, nil
}

// TODO(ericsnow) Is it too much to cat once for each executable?
const initSystemTest = `[[ "$(cat ` + pid1 + ` | awk '{print $1}')" == "%s" ]]`

// newShellSelectCommand creates a bash if statement with an if
// (or elif) clause for each of the executables in linuxExecutables.
// The body of each clause comes from calling the provided handler with
// the init system name. If the handler does not support the args then
// it returns a false "ok" value.
func newShellSelectCommand(handler func(string) (string, bool)) string {
	// TODO(ericsnow) Allow passing in "initSystems ...string".
	executables := linuxExecutables

	// TODO(ericsnow) build the command in a better way?

	cmdAll := ""
	for _, initSystem := range executables {
		cmd, ok := handler(initSystem.name)
		if !ok {
			continue
		}

		test := fmt.Sprintf(initSystemTest, initSystem.executable)
		cmd = fmt.Sprintf("if %s; then %s\n", test, cmd)
		if cmdAll != "" {
			cmd = "el" + cmd
		}
		cmdAll += cmd
	}
	if cmdAll != "" {
		cmdAll += "" +
			"else exit 1\n" +
			"fi"
	}
	return cmdAll
}
<commit_msg>Be less clever with error messages.<commit_after>package service

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

	"github.com/juju/errors"

	"github.com/juju/juju/service/common"
	"github.com/juju/juju/version"
)

var jujuVersion = version.Current

// DiscoverService returns an interface to a service apropriate
// for the current system
func DiscoverService(name string, conf common.Conf) (Service, error) {
	initName, err := discoverLocalInitSystem()
	if errors.IsNotFound(err) {
		// Fall back to checking the juju version.
		versionInitName, ok := VersionInitSystem(jujuVersion)
		if !ok {
			// The key error is the one from discoverLocalInitSystem so
			// that is what we return. However, we at least log the
			// failed fallback attempt.
			logger.Errorf("could not identify init system from %v", jujuVersion)
			return nil, errors.Trace(err)
		}
		initName = versionInitName
	} else if err != nil {
		return nil, errors.Trace(err)
	}

	service, err := NewService(name, conf, initName)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return service, nil
}

// VersionInitSystem returns an init system name based on the provided
// version info. If one cannot be identified then false if returned
// for the second return value.
func VersionInitSystem(vers version.Binary) (string, bool) {
	switch vers.OS {
	case version.Windows:
		return InitSystemWindows, true
	case version.Ubuntu:
		switch vers.Series {
		case "precise", "quantal", "raring", "saucy", "trusty", "utopic":
			return InitSystemUpstart, true
		case "":
			return "", false
		default:
			// Check for pre-precise releases.
			os, _ := version.GetOSFromSeries(vers.Series)
			if os == version.Unknown {
				return "", false
			}
			// vivid and later
			return InitSystemSystemd, true
		}
		// TODO(ericsnow) Support other OSes, like version.CentOS.
	default:
		return "", false
	}
}

const pid1 = "/proc/1/cmdline"

type initSystem struct {
	executable string
	name       string
}

var linuxExecutables = []initSystem{
	// Note that some systems link /sbin/init to whatever init system
	// is supported, so in the future we may need some other way to
	// identify upstart uniquely.
	{"/sbin/init", InitSystemUpstart},
	{"/sbin/upstart", InitSystemUpstart},
	{"/sbin/systemd", InitSystemSystemd},
	{"/bin/systemd", InitSystemSystemd},
	{"/lib/systemd/systemd", InitSystemSystemd},
}

func identifyInitSystem(executable string) (string, bool) {
	for _, initSystem := range linuxExecutables {
		if executable == initSystem.executable {
			return initSystem.name, true
		}
	}
	return "", false
}

var runtimeOS = runtime.GOOS
var pid1File = pid1

func discoverLocalInitSystem() (string, error) {
	if runtimeOS == "windows" {
		return InitSystemWindows, nil
	}

	data, err := ioutil.ReadFile(pid1File)
	if os.IsNotExist(err) {
		return "", errors.NotFoundf("init system")
	}
	if err != nil {
		return "", errors.Trace(err)
	}
	out := strings.Trim(strings.TrimSpace(string(data)), "\x00")
	executable := strings.Fields(out)[0]

	initName, ok := identifyInitSystem(executable)
	if !ok {
		return "", errors.NotFoundf("init system (based on %q)", executable)
	}
	logger.Debugf("discovered init system %q from executable %q", initName, executable)
	return initName, nil
}

// TODO(ericsnow) Is it too much to cat once for each executable?
const initSystemTest = `[[ "$(cat ` + pid1 + ` | awk '{print $1}')" == "%s" ]]`

// newShellSelectCommand creates a bash if statement with an if
// (or elif) clause for each of the executables in linuxExecutables.
// The body of each clause comes from calling the provided handler with
// the init system name. If the handler does not support the args then
// it returns a false "ok" value.
func newShellSelectCommand(handler func(string) (string, bool)) string {
	// TODO(ericsnow) Allow passing in "initSystems ...string".
	executables := linuxExecutables

	// TODO(ericsnow) build the command in a better way?

	cmdAll := ""
	for _, initSystem := range executables {
		cmd, ok := handler(initSystem.name)
		if !ok {
			continue
		}

		test := fmt.Sprintf(initSystemTest, initSystem.executable)
		cmd = fmt.Sprintf("if %s; then %s\n", test, cmd)
		if cmdAll != "" {
			cmd = "el" + cmd
		}
		cmdAll += cmd
	}
	if cmdAll != "" {
		cmdAll += "" +
			"else exit 1\n" +
			"fi"
	}
	return cmdAll
}
<|endoftext|>


<commit_before>package seriesByTag

import (
	"github.com/go-graphite/carbonapi/expr/interfaces"
	"github.com/go-graphite/carbonapi/expr/types"
	"github.com/go-graphite/carbonapi/pkg/parser"

	//"strings"
)

type seriesByTag struct {
	interfaces.FunctionBase
}

func GetOrder() interfaces.Order {
	return interfaces.Any
}

func New(configFile string) []interfaces.FunctionMetadata {
	res := make([]interfaces.FunctionMetadata, 0)
	f := &seriesByTag{}
	for _, n := range []string{"seriesByTag"} {
		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
	}
	return res
}

func (f *seriesByTag) Do(e parser.Expr, from, until int32, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
	var results []*types.MetricData
	key := parser.MetricRequest{Metric: e.ToString(), From: from, Until: until}
	data, ok := values[key]
	if !ok {
		return results, nil
	}
	return data, nil
}

// Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web
func (f *seriesByTag) Description() map[string]types.FunctionDescription {
	return map[string]types.FunctionDescription{
		"seriesByTag": {
			Description: "Returns a SeriesList of series matching all the specified tag expressions.\n\nExample:\n\n.. code-block:: none\n\n  &target=seriesByTag(\"tag1=value1\",\"tag2!=value2\")\n\nReturns a seriesList of all series that have tag1 set to value1, AND do not have tag2 set to value2.\n\nTags specifiers are strings, and may have the following formats:\n\n.. code-block:: none\n\n  tag=spec    tag value exactly matches spec\n  tag!=spec   tag value does not exactly match spec\n  tag=~value  tag value matches the regular expression spec\n  tag!=~spec  tag value does not match the regular expression spec\n\nAny tag spec that matches an empty value is considered to match series that don't have that tag.\n\nAt least one tag spec must require a non-empty value.\n\nRegular expression conditions are treated as being anchored at the start of the value.\n\nSee :ref:`querying tagged series <querying-tagged-series>` for more detail.",
			Function:    "seriesByTag(*tagExpressions)",
			Group:       "Special",
			Module:      "graphite.render.functions",
			Name:        "seriesByTag",
			Params: []types.FunctionParam{
				{
					Name:     "tagExpressions",
					Required: true,
					Type:     types.String,
					Multiple: true,
				},
			},
		},
	}
}
<commit_msg>hotfix<commit_after>package seriesByTag

import (
	"github.com/go-graphite/carbonapi/expr/interfaces"
	"github.com/go-graphite/carbonapi/expr/types"
	"github.com/go-graphite/carbonapi/pkg/parser"
	//"strings"
)

type seriesByTag struct {
	interfaces.FunctionBase
}

func GetOrder() interfaces.Order {
	return interfaces.Any
}

func New(configFile string) []interfaces.FunctionMetadata {
	res := make([]interfaces.FunctionMetadata, 0)
	f := &seriesByTag{}
	for _, n := range []string{"seriesByTag"} {
		res = append(res, interfaces.FunctionMetadata{Name: n, F: f})
	}
	return res
}

func (f *seriesByTag) Do(e parser.Expr, from, until int64, values map[parser.MetricRequest][]*types.MetricData) ([]*types.MetricData, error) {
	var results []*types.MetricData
	key := parser.MetricRequest{Metric: e.ToString(), From: from, Until: until}
	data, ok := values[key]
	if !ok {
		return results, nil
	}
	return data, nil
}

// Description is auto-generated description, based on output of https://github.com/graphite-project/graphite-web
func (f *seriesByTag) Description() map[string]types.FunctionDescription {
	return map[string]types.FunctionDescription{
		"seriesByTag": {
			Description: "Returns a SeriesList of series matching all the specified tag expressions.\n\nExample:\n\n.. code-block:: none\n\n  &target=seriesByTag(\"tag1=value1\",\"tag2!=value2\")\n\nReturns a seriesList of all series that have tag1 set to value1, AND do not have tag2 set to value2.\n\nTags specifiers are strings, and may have the following formats:\n\n.. code-block:: none\n\n  tag=spec    tag value exactly matches spec\n  tag!=spec   tag value does not exactly match spec\n  tag=~value  tag value matches the regular expression spec\n  tag!=~spec  tag value does not match the regular expression spec\n\nAny tag spec that matches an empty value is considered to match series that don't have that tag.\n\nAt least one tag spec must require a non-empty value.\n\nRegular expression conditions are treated as being anchored at the start of the value.\n\nSee :ref:`querying tagged series <querying-tagged-series>` for more detail.",
			Function:    "seriesByTag(*tagExpressions)",
			Group:       "Special",
			Module:      "graphite.render.functions",
			Name:        "seriesByTag",
			Params: []types.FunctionParam{
				{
					Name:     "tagExpressions",
					Required: true,
					Type:     types.String,
					Multiple: true,
				},
			},
		},
	}
}
<|endoftext|>


<commit_before>// Package sessions contains middleware for easy session management in Martini.
//
//  package main
//
//  import (
//    "github.com/codegangsta/martini"
//    "github.com/codegangsta/martini-contrib/sessions"
//  )
//
//  func main() {
// 	  m := martini.Classic()
//
// 	  store := sessions.NewCookieStore([]byte("secret123"))
// 	  m.Use(sessions.Sessions("my_session", store))
//
// 	  m.Get("/", func(session sessions.Session) string {
// 		  session.Set("hello", "world")
// 	  })
//  }
package sessions

import (
	"github.com/codegangsta/martini"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"log"
	"net/http"
)

const (
	errorFormat = "[sessions] ERROR! %s\n"
)

// Store is an interface for custom session stores.
type Store interface {
	sessions.Store
}

// NewCookieStore returns a new CookieStore.
//
// Keys are defined in pairs to allow key rotation, but the common case is to set a single
// authentication key and optionally an encryption key.
//
// The first key in a pair is used for authentication and the second for encryption. The
// encryption key can be set to nil or omitted in the last pair, but the authentication key
// is required in all pairs.
//
// It is recommended to use an authentication key with 32 or 64 bytes. The encryption key,
// if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.
func NewCookieStore(keyPairs ...[]byte) Store {
	return sessions.NewCookieStore(keyPairs...)
}

// Session stores the values and optional configuration for a session.
type Session interface {
	// Get returns the session value associated to the given key.
	Get(key interface{}) interface{}
	// Set sets the session value associated to the given key.
	Set(key interface{}, val interface{})
	// AddFlash adds a flash message to the session.
	// A single variadic argument is accepted, and it is optional: it defines the flash key.
	// If not defined "_flash" is used by default.
	//AddFlash(value interface{}, vars ...string)
	// Flashes returns a slice of flash messages from the session.
	// A single variadic argument is accepted, and it is optional: it defines the flash key.
	// If not defined "_flash" is used by default.
	//Flashes(vars ...string) []interface{}
}

// Sessions is a Middleware that maps a session.Session service into the Martini handler chain.
// Sessions can use a number of storage solutions with the given store.
func Sessions(name string, store Store) martini.Handler {
	return func(res http.ResponseWriter, r *http.Request, c martini.Context, l *log.Logger) {
		// Map to the Session interface
		s := &session{name, r, l, store, nil, false}
		c.MapTo(s, (*Session)(nil))

		// clear the context, we don't need to use
		// gorilla context and we don't want memory leaks
		defer context.Clear(r)

		// Use before hook to save out the session
		rw := res.(martini.ResponseWriter)
		rw.Before(func(martini.ResponseWriter) {
			if s.Written() {
				check(s.Session().Save(r, res), l)
			}
		})
	}
}

type session struct {
	name    string
	request *http.Request
	logger  *log.Logger
	store   Store
	session *sessions.Session
	written bool
}

func (s *session) Get(key interface{}) interface{} {
	return s.Session().Values[key]
}

func (s *session) Set(key interface{}, val interface{}) {
	s.Session().Values[key] = val
	s.written = true
}

func (s *session) Session() *sessions.Session {
	if s.session == nil {
		s.session, _ = s.store.Get(s.request, s.name)
	}

	return s.session
}

func (s *session) Written() bool {
	return s.written
}

func check(err error, l *log.Logger) {
	if err != nil {
		l.Printf(errorFormat, err)
	}
}
<commit_msg>JMS #38: Error handling for store.Get<commit_after>// Package sessions contains middleware for easy session management in Martini.
//
//  package main
//
//  import (
//    "github.com/codegangsta/martini"
//    "github.com/codegangsta/martini-contrib/sessions"
//  )
//
//  func main() {
// 	  m := martini.Classic()
//
// 	  store := sessions.NewCookieStore([]byte("secret123"))
// 	  m.Use(sessions.Sessions("my_session", store))
//
// 	  m.Get("/", func(session sessions.Session) string {
// 		  session.Set("hello", "world")
// 	  })
//  }
package sessions

import (
	"github.com/codegangsta/martini"
	"github.com/gorilla/context"
	"github.com/gorilla/sessions"
	"log"
	"net/http"
)

const (
	errorFormat = "[sessions] ERROR! %s\n"
)

// Store is an interface for custom session stores.
type Store interface {
	sessions.Store
}

// NewCookieStore returns a new CookieStore.
//
// Keys are defined in pairs to allow key rotation, but the common case is to set a single
// authentication key and optionally an encryption key.
//
// The first key in a pair is used for authentication and the second for encryption. The
// encryption key can be set to nil or omitted in the last pair, but the authentication key
// is required in all pairs.
//
// It is recommended to use an authentication key with 32 or 64 bytes. The encryption key,
// if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes.
func NewCookieStore(keyPairs ...[]byte) Store {
	return sessions.NewCookieStore(keyPairs...)
}

// Session stores the values and optional configuration for a session.
type Session interface {
	// Get returns the session value associated to the given key.
	Get(key interface{}) interface{}
	// Set sets the session value associated to the given key.
	Set(key interface{}, val interface{})
	// AddFlash adds a flash message to the session.
	// A single variadic argument is accepted, and it is optional: it defines the flash key.
	// If not defined "_flash" is used by default.
	//AddFlash(value interface{}, vars ...string)
	// Flashes returns a slice of flash messages from the session.
	// A single variadic argument is accepted, and it is optional: it defines the flash key.
	// If not defined "_flash" is used by default.
	//Flashes(vars ...string) []interface{}
}

// Sessions is a Middleware that maps a session.Session service into the Martini handler chain.
// Sessions can use a number of storage solutions with the given store.
func Sessions(name string, store Store) martini.Handler {
	return func(res http.ResponseWriter, r *http.Request, c martini.Context, l *log.Logger) {
		// Map to the Session interface
		s := &session{name, r, l, store, nil, false}
		c.MapTo(s, (*Session)(nil))

		// clear the context, we don't need to use
		// gorilla context and we don't want memory leaks
		defer context.Clear(r)

		// Use before hook to save out the session
		rw := res.(martini.ResponseWriter)
		rw.Before(func(martini.ResponseWriter) {
			if s.Written() {
				check(s.Session().Save(r, res), l)
			}
		})
	}
}

type session struct {
	name    string
	request *http.Request
	logger  *log.Logger
	store   Store
	session *sessions.Session
	written bool
}

func (s *session) Get(key interface{}) interface{} {
	return s.Session().Values[key]
}

func (s *session) Set(key interface{}, val interface{}) {
	s.Session().Values[key] = val
	s.written = true
}

func (s *session) Session() *sessions.Session {
	if s.session == nil {
		var err error
		s.session, err = s.store.Get(s.request, s.name)
		check(err, s.logger)
	}

	return s.session
}

func (s *session) Written() bool {
	return s.written
}

func check(err error, l *log.Logger) {
	if err != nil {
		l.Printf(errorFormat, err)
	}
}
<|endoftext|>


<commit_before>package github

import (
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/crosbymichael/octokat"
)

func (g GitHub) IssueInfoCheck(issueHook *octokat.IssueHook) error {
	body := strings.ToLower(issueHook.Issue.Body)
	title := strings.ToLower(issueHook.Issue.Title)

	// we don't care about proposals or features
	if strings.Contains(title, "proposal") || strings.Contains(title, "feature") {
		log.Debugf("Issue is talking about a proposal or feature so ignoring.")
		return nil
	}

	// parse if they gave us
	// docker info, docker version, uname -a
	if !strings.Contains(body, "docker version") || !strings.Contains(body, "docker info") || !strings.Contains(body, "uname -a") {
		// get content
		repo := getRepo(issueHook.Repo)
		content, err := g.getContent(repo, issueHook.Issue.Number, false)
		if err != nil {
			return err
		}

		// comment on the issue
		log.Debugf("commenting on issue %d about needing more info", issueHook.Issue.Number)
		if err := g.addNeedMoreInfoComment(repo, issueHook.Issue.Number, content); err != nil {
			return err
		}
	}

	return nil
}

func (g GitHub) LabelIssueComment(issueHook *octokat.IssueHook) error {
	var labelmap map[string]string = map[string]string{
		"#dibs":    "status/claimed",
		"#claimed": "status/claimed",
		"#mine":    "status/claimed",
	}

	repo := getRepo(issueHook.Repo)

	for token, label := range labelmap {
		// if comment matches predefined actions AND author is not bot
		if strings.Contains(strings.ToLower(issueHook.Comment.Body), token) && g.User != issueHook.Sender.Login {
			log.Debugf("Adding label %#v to issue %d", label, issueHook.Issue.Number)
			if err := g.addLabel(repo, issueHook.Issue.Number, label); err != nil {
				return err
			}
			log.Infof("Added label %#v to issue %d", label, issueHook.Issue.Number)
		}
	}

	return nil
}
<commit_msg>Collect +1 opinions in a single comment.<commit_after>package github

import (
	"fmt"
	"strconv"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/crosbymichael/octokat"
)

const (
	pollKey      = "USER POLL"
	pollTemplate = `*USER POLL*

*The best way to get notified when there are changes in this discussion is by clicking the Subscribe button in the top right.*

The people listed below have appreciated your meaningfull discussion with a random +1:
`
)

func (g GitHub) IssueInfoCheck(issueHook *octokat.IssueHook) error {
	body := strings.ToLower(issueHook.Issue.Body)
	title := strings.ToLower(issueHook.Issue.Title)

	// we don't care about proposals or features
	if strings.Contains(title, "proposal") || strings.Contains(title, "feature") {
		log.Debugf("Issue is talking about a proposal or feature so ignoring.")
		return nil
	}

	// parse if they gave us
	// docker info, docker version, uname -a
	if !strings.Contains(body, "docker version") || !strings.Contains(body, "docker info") || !strings.Contains(body, "uname -a") {
		// get content
		repo := getRepo(issueHook.Repo)
		content, err := g.getContent(repo, issueHook.Issue.Number, false)
		if err != nil {
			return err
		}

		// comment on the issue
		log.Debugf("commenting on issue %d about needing more info", issueHook.Issue.Number)
		if err := g.addNeedMoreInfoComment(repo, issueHook.Issue.Number, content); err != nil {
			return err
		}
	}

	return nil
}

func (g GitHub) LabelIssueComment(issueHook *octokat.IssueHook) error {
	if err := g.maybeClaimIssue(issueHook); err != nil {
		return err
	}

	return g.maybeOpinion(issueHook)
}

func (g GitHub) maybeClaimIssue(issueHook *octokat.IssueHook) error {
	var labelmap map[string]string = map[string]string{
		"#dibs":    "status/claimed",
		"#claimed": "status/claimed",
		"#mine":    "status/claimed",
	}

	repo := getRepo(issueHook.Repo)

	for token, label := range labelmap {
		// if comment matches predefined actions AND author is not bot
		if strings.Contains(strings.ToLower(issueHook.Comment.Body), token) && g.User != issueHook.Sender.Login {
			log.Debugf("Adding label %#v to issue %d", label, issueHook.Issue.Number)
			if err := g.addLabel(repo, issueHook.Issue.Number, label); err != nil {
				return err
			}
			log.Infof("Added label %#v to issue %d", label, issueHook.Issue.Number)
		}
	}
	return nil
}

func (g GitHub) maybeOpinion(issueHook *octokat.IssueHook) error {
	body := strings.TrimSpace(issueHook.Comment.Body)

	if body == "+1" {
		login := issueHook.Comment.User.Login
		commenters := map[string]int{login: issueHook.Comment.Id}

		options := &octokat.Options{
			QueryParams: map[string]string{"per_page": "100"},
		}

		repo := getRepo(issueHook.Repo)
		issueId := strconv.Itoa(issueHook.Issue.Number)
		comments, err := g.Client().Comments(repo, issueId, options)
		if err != nil {
			return err
		}

		var poll octokat.Comment

		for _, c := range comments {
			if strings.ToLower(c.User.Login) == g.User && strings.Contains(c.Body, pollKey) {
				poll = c
			} else if strings.TrimSpace(c.Body) == "+1" {
				commenters[c.User.Login] = c.Id
			}
		}

		if poll.Body != "" {
			if !strings.Contains(poll.Body, login) {
				for k, _ := range commenters {
					poll.Body += fmt.Sprintf("\n@%s", k)
				}
				if _, err := g.Client().PatchComment(repo, strconv.Itoa(poll.Id), poll.Body); err != nil {
					return err
				}
			}
		} else {
			tmpl := pollTemplate
			for k, _ := range commenters {
				tmpl += fmt.Sprintf("\n@%s", k)
			}
			if _, err := g.Client().AddComment(repo, issueId, tmpl); err != nil {
				return err
			}
		}

		for _, v := range commenters {
			if err := g.Client().RemoveComment(repo, v); err != nil {
				return err
			}
		}
	}

	return nil
}
<|endoftext|>


<commit_before>package job

import (
	"github.com/telemetryapp/gotelemetry"
)

// Interfaces

type PluginInstance interface {
	Init(job *Job) error
	Run(job *Job)
	Reconfigure(job *Job, config map[string]interface{}) error
	Terminate(job *Job)
}

type PluginFactory func() PluginInstance

// Manager

type pluginManager struct {
	factories map[string]PluginFactory
}

var pluginErrors = []error{}

var manager = &pluginManager{map[string]PluginFactory{}}

func RegisterPlugin(name string, factory PluginFactory) {
	if _, exists := manager.factories[name]; exists {
		pluginErrors = append(pluginErrors, gotelemetry.NewError(500, "Duplicate plugin name `"+name+"`"))
		return
	}

	manager.factories[name] = factory
}

func AllPlugins() map[string]PluginFactory {
	return manager.factories
}

func GetPlugin(name string) (PluginFactory, error) {
	result, success := manager.factories[name]

	if !success {
		return nil, gotelemetry.NewError(500, "Plugin `"+name+"` not found")
	}

	return result, nil
}

func GetPluginRegistrationErrors() []error {
	return pluginErrors
}
<commit_msg>- Docs<commit_after>package job

import (
	"github.com/telemetryapp/gotelemetry"
)

// Interfaces

// Interface PluginInstance represents an instance of a plugin that is called upon to perform a job.
//
// In other words, this is what you are supposed to write.
type PluginInstance interface {
	Init(job *Job) error                                       // Initializes the instance
	Run(job *Job)                                              // Runs the instance synchronously until Terminate() is called
	Reconfigure(job *Job, config map[string]interface{}) error // Dynamically reconfigures the instance, or returns an error if it can't
	Terminate(job *Job)                                        // Terminates the instance, returning only when its execution is complete
}

type PluginFactory func() PluginInstance

// Manager

type pluginManager struct {
	factories map[string]PluginFactory
}

var pluginErrors = []error{}

var manager = &pluginManager{map[string]PluginFactory{}}

func RegisterPlugin(name string, factory PluginFactory) {
	if _, exists := manager.factories[name]; exists {
		pluginErrors = append(pluginErrors, gotelemetry.NewError(500, "Duplicate plugin name `"+name+"`"))
		return
	}

	manager.factories[name] = factory
}

func AllPlugins() map[string]PluginFactory {
	return manager.factories
}

func GetPlugin(name string) (PluginFactory, error) {
	result, success := manager.factories[name]

	if !success {
		return nil, gotelemetry.NewError(500, "Plugin `"+name+"` not found")
	}

	return result, nil
}

func GetPluginRegistrationErrors() []error {
	return pluginErrors
}
<|endoftext|>


<commit_before>package glacier

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/rdwilliamson/aws"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

type jobRequest struct {
	Type        string
	ArchiveId   string `json:",omitempty"` // required for archive retrieval
	Description string `json:",omitempty"`
	Format      string `json:",omitempty"`
	SNSTopic    string `json:",omitempty"`
}

type Archive struct {
	ArchiveId          string
	ArchiveDescription string
	CreationDate       time.Time
	Size               uint64
	SHA256TreeHash     string
}

type Inventory struct {
	VaultARN      string
	InventoryDate time.Time
	ArchiveList   []Archive
}

// TODO write unmarshaler instead of using these structs
type archive struct {
	ArchiveId          string
	ArchiveDescription string
	CreationDate       string
	Size               uint64
	SHA256TreeHash     string
}
type inventory struct {
	VaultARN      string
	InventoryDate string
	ArchiveList   []archive
}

type Job struct {
	Action               string
	ArchiveId            string
	ArchiveSizeInBytes   uint64
	Completed            bool
	CompletionDate       time.Time
	CreationDate         time.Time
	InventorySizeInBytes uint
	JobDescription       string
	JobId                string
	SHA256TreeHash       string
	SNSTopic             string
	StatusCode           string
	StatusMessage        string
	VaultARN             string
}

// TODO write unmarshaler instead of using these structs
type job struct {
	Action               string
	ArchiveId            *string
	ArchiveSizeInBytes   *uint64
	Completed            bool
	CompletionDate       *string
	CreationDate         string
	InventorySizeInBytes *uint
	JobDescription       *string
	JobId                string
	SHA256TreeHash       *string
	SNSTopic             *string
	StatusCode           string
	StatusMessage        *string
	VaultARN             string
}
type jobList struct {
	Marker  *string
	JobList []job
}

func (c *Connection) InitiateRetrievalJob(vault, archive, topic,
	description string) (string, error) {
	j := jobRequest{Type: "archive-retrieval", ArchiveId: archive,
		Description: description, SNSTopic: topic}
	rawBody, _ := json.Marshal(j)
	body := bytes.NewReader(rawBody)

	request, err := http.NewRequest("POST",
		"https://"+c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs", body)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, body, nil)
	if err != nil {
		return "", err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return "", err
	}

	if response.StatusCode != 202 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		err = response.Body.Close()
		if err != nil {
			return "", err
		}
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return "", err
		}
		return "", e
	}

	return response.Header.Get("x-amz-job-id"), nil
}

func (c *Connection) InitiateInventoryJob(vault, description,
	topic string) (string, error) {
	j := jobRequest{Type: "inventory-retrieval", Description: description,
		SNSTopic: topic}
	rawBody, err := json.Marshal(j)
	if err != nil {
		return "", err
	}
	body := bytes.NewReader(rawBody)

	request, err := http.NewRequest("POST",
		"https://"+c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs", body)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, body, nil)
	if err != nil {
		return "", err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return "", err
	}

	if response.StatusCode != 202 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		err = response.Body.Close()
		if err != nil {
			return "", err
		}
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return "", err
		}
		return "", e
	}

	return response.Header.Get("x-amz-job-id"), nil
}

func (c *Connection) DescribeJob(vault, jobId string) (*Job, error) {
	request, err := http.NewRequest("GET", "https://"+
		c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs/"+jobId+"/output",
		nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil, nil)

	response, err := c.Client.Do(request)
	if err != nil {
		return nil, err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	response.Body.Close()

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return nil, err
		}
		return nil, &e
	}

	var j job
	err = json.Unmarshal(body, &j)
	if err != nil {
		return nil, err
	}

	var result Job
	if j.ArchiveId != nil {
		result.ArchiveId = *j.ArchiveId
	}
	if j.ArchiveSizeInBytes != nil {
		result.ArchiveSizeInBytes = *j.ArchiveSizeInBytes
	}
	result.Completed = j.Completed
	if j.CompletionDate != nil {
		result.CompletionDate, err = time.Parse(time.RFC3339, *j.CompletionDate)
	}
	result.CreationDate, err = time.Parse(time.RFC3339, j.CreationDate)
	if j.InventorySizeInBytes != nil {
		result.InventorySizeInBytes = *j.InventorySizeInBytes
	}
	if j.JobDescription != nil {
		result.JobDescription = *j.JobDescription
	}
	result.JobId = j.JobId
	if j.SHA256TreeHash != nil {
		result.SHA256TreeHash = *j.SHA256TreeHash
	}
	if j.SNSTopic != nil {
		result.SNSTopic = *j.SNSTopic
	}
	result.StatusCode = j.StatusCode
	if j.StatusMessage != nil {
		result.StatusMessage = *j.StatusMessage
	}
	result.VaultARN = j.VaultARN

	return nil, nil
}

func (c *Connection) GetRetrievalJob(vault, job string, start, end uint) (io.ReadCloser, error) {
	request, err := http.NewRequest("GET", "https://"+
		c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs/"+job+"/output",
		nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")
	if end > 0 {
		request.Header.Add("Range", fmt.Sprintf("bytes %d-%d/*", start, end))
	}

	c.Signature.Sign(request, nil, nil)

	response, err := c.Client.Do(request)
	if err != nil {
		return nil, err
	}

	if response.StatusCode != 200 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return nil, err
		}
		response.Body.Close()

		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return nil, err
		}
		return nil, e
	}

	// TODO return content range and x-amz-sha256-tree-hash
	return response.Body, nil
}

func (c *Connection) GetInventoryJob(vault, job string) (Inventory, error) {
	request, err := http.NewRequest("GET", "https://"+
		c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs/"+job+"/output",
		nil)
	if err != nil {
		return Inventory{}, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, nil, nil)
	if err != nil {
		return Inventory{}, err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return Inventory{}, err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return Inventory{}, err
	}
	err = response.Body.Close()
	if err != nil {
		return Inventory{}, err
	}

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return Inventory{}, err
		}
		return Inventory{}, e
	}

	var i inventory
	err = json.Unmarshal(body, &i)
	if err != nil {
		return Inventory{}, err
	}

	var result Inventory
	result.VaultARN = i.VaultARN
	result.InventoryDate, err = time.Parse(time.RFC3339, i.InventoryDate)
	if err != nil {
		return Inventory{}, err
	}
	result.ArchiveList = make([]Archive, len(i.ArchiveList))
	for j, v := range i.ArchiveList {
		result.ArchiveList[j].ArchiveId = v.ArchiveId
		result.ArchiveList[j].ArchiveDescription = v.ArchiveDescription
		result.ArchiveList[j].CreationDate, err = time.Parse(time.RFC3339,
			v.CreationDate)
		if err != nil {
			return Inventory{}, err
		}
		result.ArchiveList[j].Size = v.Size
		result.ArchiveList[j].SHA256TreeHash = v.SHA256TreeHash
	}

	return result, nil
}

func (c *Connection) ListJobs(vault, completed, limit, marker,
	statusCode string) ([]Job, string, error) {
	get, err := url.Parse("https://" + c.Signature.Region.Glacier +
		"/-/vaults/" + vault + "/jobs")
	if err != nil {
		return nil, "", err
	}

	query := get.Query()
	if completed != "" {
		// TODO validate, true or false
		query.Add("completed", completed)
	}
	if limit != "" {
		// TODO validate, 1 - 1000
		query.Add("limit", limit)
	}
	if marker != "" {
		// TODO validate
		query.Add("marker", marker)
	}
	if statusCode != "" {
		// TODO validate, InProgress, Succeeded, or Failed
		query.Add("statuscode", statusCode)
	}
	get.RawQuery = query.Encode()

	request, err := http.NewRequest("GET", get.String(), nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil, nil)

	response, err := c.Client.Do(request)
	if err != nil {
		return nil, "", err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, "", err
	}
	err = response.Body.Close()
	if err != nil {
		return nil, "", err
	}

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return nil, "", err
		}
		return nil, "", e
	}

	var jl jobList
	err = json.Unmarshal(body, &jl)
	if err != nil {
		return nil, "", err
	}

	var err1 error
	jobs := make([]Job, len(jl.JobList))
	for i, v := range jl.JobList {
		jobs[i].Action = v.Action
		if v.ArchiveId != nil {
			jobs[i].ArchiveId = *v.ArchiveId
		}
		if v.ArchiveSizeInBytes != nil {
			jobs[i].ArchiveSizeInBytes = *v.ArchiveSizeInBytes
		}
		jobs[i].Completed = v.Completed
		if v.CompletionDate != nil {
			jobs[i].CompletionDate, err = time.Parse(time.RFC3339, *v.CompletionDate)
		}
		if err != nil {
			err1 = err
		}
		jobs[i].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			err1 = err
		}
		if v.InventorySizeInBytes != nil {
			jobs[i].InventorySizeInBytes = *v.InventorySizeInBytes
		}
		if v.JobDescription != nil {
			jobs[i].JobDescription = *v.JobDescription
		}
		jobs[i].JobId = v.JobId
		if v.SHA256TreeHash != nil {
			jobs[i].SHA256TreeHash = *v.SHA256TreeHash
		}
		if v.SNSTopic != nil {
			jobs[i].SNSTopic = *v.SNSTopic
		}
		jobs[i].StatusCode = v.StatusCode
		if v.StatusMessage != nil {
			jobs[i].StatusMessage = *v.StatusMessage
		}
		jobs[i].VaultARN = v.VaultARN
	}

	var m string
	if jl.Marker != nil {
		m = *jl.Marker
	}

	return jobs, m, err1
}
<commit_msg>When describing job get the job and not its output, also return the result.<commit_after>package glacier

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/rdwilliamson/aws"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

type jobRequest struct {
	Type        string
	ArchiveId   string `json:",omitempty"` // required for archive retrieval
	Description string `json:",omitempty"`
	Format      string `json:",omitempty"`
	SNSTopic    string `json:",omitempty"`
}

type Archive struct {
	ArchiveId          string
	ArchiveDescription string
	CreationDate       time.Time
	Size               uint64
	SHA256TreeHash     string
}

type Inventory struct {
	VaultARN      string
	InventoryDate time.Time
	ArchiveList   []Archive
}

// TODO write unmarshaler instead of using these structs
type archive struct {
	ArchiveId          string
	ArchiveDescription string
	CreationDate       string
	Size               uint64
	SHA256TreeHash     string
}
type inventory struct {
	VaultARN      string
	InventoryDate string
	ArchiveList   []archive
}

type Job struct {
	Action               string
	ArchiveId            string
	ArchiveSizeInBytes   uint64
	Completed            bool
	CompletionDate       time.Time
	CreationDate         time.Time
	InventorySizeInBytes uint
	JobDescription       string
	JobId                string
	SHA256TreeHash       string
	SNSTopic             string
	StatusCode           string
	StatusMessage        string
	VaultARN             string
}

// TODO write unmarshaler instead of using these structs
type job struct {
	Action               string
	ArchiveId            *string
	ArchiveSizeInBytes   *uint64
	Completed            bool
	CompletionDate       *string
	CreationDate         string
	InventorySizeInBytes *uint
	JobDescription       *string
	JobId                string
	SHA256TreeHash       *string
	SNSTopic             *string
	StatusCode           string
	StatusMessage        *string
	VaultARN             string
}
type jobList struct {
	Marker  *string
	JobList []job
}

func (c *Connection) InitiateRetrievalJob(vault, archive, topic,
	description string) (string, error) {
	j := jobRequest{Type: "archive-retrieval", ArchiveId: archive,
		Description: description, SNSTopic: topic}
	rawBody, _ := json.Marshal(j)
	body := bytes.NewReader(rawBody)

	request, err := http.NewRequest("POST",
		"https://"+c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs", body)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, body, nil)
	if err != nil {
		return "", err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return "", err
	}

	if response.StatusCode != 202 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		err = response.Body.Close()
		if err != nil {
			return "", err
		}
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return "", err
		}
		return "", e
	}

	return response.Header.Get("x-amz-job-id"), nil
}

func (c *Connection) InitiateInventoryJob(vault, description,
	topic string) (string, error) {
	j := jobRequest{Type: "inventory-retrieval", Description: description,
		SNSTopic: topic}
	rawBody, err := json.Marshal(j)
	if err != nil {
		return "", err
	}
	body := bytes.NewReader(rawBody)

	request, err := http.NewRequest("POST",
		"https://"+c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs", body)
	if err != nil {
		return "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, body, nil)
	if err != nil {
		return "", err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return "", err
	}

	if response.StatusCode != 202 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return "", err
		}
		err = response.Body.Close()
		if err != nil {
			return "", err
		}
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return "", err
		}
		return "", e
	}

	return response.Header.Get("x-amz-job-id"), nil
}

func (c *Connection) DescribeJob(vault, jobId string) (*Job, error) {
	request, err := http.NewRequest("GET", "https://"+
		c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs/"+jobId,
		nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil, nil)

	response, err := c.Client.Do(request)
	if err != nil {
		return nil, err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}
	response.Body.Close()

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return nil, err
		}
		return nil, &e
	}

	var j job
	err = json.Unmarshal(body, &j)
	if err != nil {
		return nil, err
	}

	var result Job
	if j.ArchiveId != nil {
		result.ArchiveId = *j.ArchiveId
	}
	if j.ArchiveSizeInBytes != nil {
		result.ArchiveSizeInBytes = *j.ArchiveSizeInBytes
	}
	result.Completed = j.Completed
	if j.CompletionDate != nil {
		result.CompletionDate, err = time.Parse(time.RFC3339, *j.CompletionDate)
	}
	result.CreationDate, err = time.Parse(time.RFC3339, j.CreationDate)
	if j.InventorySizeInBytes != nil {
		result.InventorySizeInBytes = *j.InventorySizeInBytes
	}
	if j.JobDescription != nil {
		result.JobDescription = *j.JobDescription
	}
	result.JobId = j.JobId
	if j.SHA256TreeHash != nil {
		result.SHA256TreeHash = *j.SHA256TreeHash
	}
	if j.SNSTopic != nil {
		result.SNSTopic = *j.SNSTopic
	}
	result.StatusCode = j.StatusCode
	if j.StatusMessage != nil {
		result.StatusMessage = *j.StatusMessage
	}
	result.VaultARN = j.VaultARN

	return &result, nil
}

func (c *Connection) GetRetrievalJob(vault, job string, start, end uint) (io.ReadCloser, error) {
	request, err := http.NewRequest("GET", "https://"+
		c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs/"+job+"/output",
		nil)
	if err != nil {
		return nil, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")
	if end > 0 {
		request.Header.Add("Range", fmt.Sprintf("bytes %d-%d/*", start, end))
	}

	c.Signature.Sign(request, nil, nil)

	response, err := c.Client.Do(request)
	if err != nil {
		return nil, err
	}

	if response.StatusCode != 200 {
		body, err := ioutil.ReadAll(response.Body)
		if err != nil {
			return nil, err
		}
		response.Body.Close()

		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return nil, err
		}
		return nil, e
	}

	// TODO return content range and x-amz-sha256-tree-hash
	return response.Body, nil
}

func (c *Connection) GetInventoryJob(vault, job string) (Inventory, error) {
	request, err := http.NewRequest("GET", "https://"+
		c.Signature.Region.Glacier+"/-/vaults/"+vault+"/jobs/"+job+"/output",
		nil)
	if err != nil {
		return Inventory{}, err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	err = c.Signature.Sign(request, nil, nil)
	if err != nil {
		return Inventory{}, err
	}

	response, err := c.Client.Do(request)
	if err != nil {
		return Inventory{}, err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return Inventory{}, err
	}
	err = response.Body.Close()
	if err != nil {
		return Inventory{}, err
	}

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return Inventory{}, err
		}
		return Inventory{}, e
	}

	var i inventory
	err = json.Unmarshal(body, &i)
	if err != nil {
		return Inventory{}, err
	}

	var result Inventory
	result.VaultARN = i.VaultARN
	result.InventoryDate, err = time.Parse(time.RFC3339, i.InventoryDate)
	if err != nil {
		return Inventory{}, err
	}
	result.ArchiveList = make([]Archive, len(i.ArchiveList))
	for j, v := range i.ArchiveList {
		result.ArchiveList[j].ArchiveId = v.ArchiveId
		result.ArchiveList[j].ArchiveDescription = v.ArchiveDescription
		result.ArchiveList[j].CreationDate, err = time.Parse(time.RFC3339,
			v.CreationDate)
		if err != nil {
			return Inventory{}, err
		}
		result.ArchiveList[j].Size = v.Size
		result.ArchiveList[j].SHA256TreeHash = v.SHA256TreeHash
	}

	return result, nil
}

func (c *Connection) ListJobs(vault, completed, limit, marker,
	statusCode string) ([]Job, string, error) {
	get, err := url.Parse("https://" + c.Signature.Region.Glacier +
		"/-/vaults/" + vault + "/jobs")
	if err != nil {
		return nil, "", err
	}

	query := get.Query()
	if completed != "" {
		// TODO validate, true or false
		query.Add("completed", completed)
	}
	if limit != "" {
		// TODO validate, 1 - 1000
		query.Add("limit", limit)
	}
	if marker != "" {
		// TODO validate
		query.Add("marker", marker)
	}
	if statusCode != "" {
		// TODO validate, InProgress, Succeeded, or Failed
		query.Add("statuscode", statusCode)
	}
	get.RawQuery = query.Encode()

	request, err := http.NewRequest("GET", get.String(), nil)
	if err != nil {
		return nil, "", err
	}
	request.Header.Add("x-amz-glacier-version", "2012-06-01")

	c.Signature.Sign(request, nil, nil)

	response, err := c.Client.Do(request)
	if err != nil {
		return nil, "", err
	}

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, "", err
	}
	err = response.Body.Close()
	if err != nil {
		return nil, "", err
	}

	if response.StatusCode != 200 {
		var e aws.Error
		err = json.Unmarshal(body, &e)
		if err != nil {
			return nil, "", err
		}
		return nil, "", e
	}

	var jl jobList
	err = json.Unmarshal(body, &jl)
	if err != nil {
		return nil, "", err
	}

	var err1 error
	jobs := make([]Job, len(jl.JobList))
	for i, v := range jl.JobList {
		jobs[i].Action = v.Action
		if v.ArchiveId != nil {
			jobs[i].ArchiveId = *v.ArchiveId
		}
		if v.ArchiveSizeInBytes != nil {
			jobs[i].ArchiveSizeInBytes = *v.ArchiveSizeInBytes
		}
		jobs[i].Completed = v.Completed
		if v.CompletionDate != nil {
			jobs[i].CompletionDate, err = time.Parse(time.RFC3339, *v.CompletionDate)
		}
		if err != nil {
			err1 = err
		}
		jobs[i].CreationDate, err = time.Parse(time.RFC3339, v.CreationDate)
		if err != nil {
			err1 = err
		}
		if v.InventorySizeInBytes != nil {
			jobs[i].InventorySizeInBytes = *v.InventorySizeInBytes
		}
		if v.JobDescription != nil {
			jobs[i].JobDescription = *v.JobDescription
		}
		jobs[i].JobId = v.JobId
		if v.SHA256TreeHash != nil {
			jobs[i].SHA256TreeHash = *v.SHA256TreeHash
		}
		if v.SNSTopic != nil {
			jobs[i].SNSTopic = *v.SNSTopic
		}
		jobs[i].StatusCode = v.StatusCode
		if v.StatusMessage != nil {
			jobs[i].StatusMessage = *v.StatusMessage
		}
		jobs[i].VaultARN = v.VaultARN
	}

	var m string
	if jl.Marker != nil {
		m = *jl.Marker
	}

	return jobs, m, err1
}
<|endoftext|>


<commit_before>package align

import "testing"

func TestHorizontal(t *testing.T) {
	tests := []struct {
		desc  string
		align Horizontal
		want  string
	}{
		{
			desc:  "unknown",
			align: Horizontal(-1),
			want:  "HorizontalUnknown",
		},
		{
			desc:  "left",
			align: HorizontalLeft,
			want:  "HorizontalLeft",
		},
		{
			desc:  "center",
			align: HorizontalCenter,
			want:  "HorizontalCenter",
		},
		{
			desc:  "right",
			align: HorizontalRight,
			want:  "HorizontalRight",
		},
	}

	for _, tc := range tests {
		t.Run(tc.desc, func(t *testing.T) {
			if got := tc.align.String(); got != tc.want {
				t.Errorf("String => %q, want %q", got, tc.want)
			}
		})
	}
}

func TestVertical(t *testing.T) {
	tests := []struct {
		desc  string
		align Vertical
		want  string
	}{
		{
			desc:  "unknown",
			align: Vertical(-1),
			want:  "VerticalUnknown",
		},
		{
			desc:  "top",
			align: VerticalTop,
			want:  "VerticalTop",
		},
		{
			desc:  "middle",
			align: VerticalMiddle,
			want:  "VerticalMiddle",
		},
		{
			desc:  "bottom",
			align: VerticalBottom,
			want:  "VerticalBottom",
		},
	}

	for _, tc := range tests {
		t.Run(tc.desc, func(t *testing.T) {
			if got := tc.align.String(); got != tc.want {
				t.Errorf("String => %q, want %q", got, tc.want)
			}
		})
	}
}
<commit_msg>Adding licences.<commit_after>// Copyright 2019 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package align

import "testing"

func TestHorizontal(t *testing.T) {
	tests := []struct {
		desc  string
		align Horizontal
		want  string
	}{
		{
			desc:  "unknown",
			align: Horizontal(-1),
			want:  "HorizontalUnknown",
		},
		{
			desc:  "left",
			align: HorizontalLeft,
			want:  "HorizontalLeft",
		},
		{
			desc:  "center",
			align: HorizontalCenter,
			want:  "HorizontalCenter",
		},
		{
			desc:  "right",
			align: HorizontalRight,
			want:  "HorizontalRight",
		},
	}

	for _, tc := range tests {
		t.Run(tc.desc, func(t *testing.T) {
			if got := tc.align.String(); got != tc.want {
				t.Errorf("String => %q, want %q", got, tc.want)
			}
		})
	}
}

func TestVertical(t *testing.T) {
	tests := []struct {
		desc  string
		align Vertical
		want  string
	}{
		{
			desc:  "unknown",
			align: Vertical(-1),
			want:  "VerticalUnknown",
		},
		{
			desc:  "top",
			align: VerticalTop,
			want:  "VerticalTop",
		},
		{
			desc:  "middle",
			align: VerticalMiddle,
			want:  "VerticalMiddle",
		},
		{
			desc:  "bottom",
			align: VerticalBottom,
			want:  "VerticalBottom",
		},
	}

	for _, tc := range tests {
		t.Run(tc.desc, func(t *testing.T) {
			if got := tc.align.String(); got != tc.want {
				t.Errorf("String => %q, want %q", got, tc.want)
			}
		})
	}
}
<|endoftext|>


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

// Package sqlite provides access to the SQLite library, version 3.
package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>

// These wrappers are necessary because SQLITE_TRANSIENT
// is a pointer constant, and cgo doesn't translate them correctly.
// The definition in sqlite3.h is:
//
// typedef void (*sqlite3_destructor_type)(void*);
// #define SQLITE_STATIC      ((sqlite3_destructor_type)0)
// #define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)

static int my_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
	return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
}
static int my_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
	return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
}

*/
import "C"

import (
	"fmt"
	"os"
	"reflect"
	"strconv"
	"unsafe"
	"time"
)

type Errno int

func (e Errno) String() string {
	s := errText[e]
	if s == "" {
		return fmt.Sprintf("errno %d", int(e))
	}
	return s
}

var (
	ErrError os.Error = Errno(1)  //    /* SQL error or missing database */
	ErrInternal os.Error = Errno(2)  //    /* Internal logic error in SQLite */
	ErrPerm os.Error = Errno(3)  //    /* Access permission denied */
	ErrAbort os.Error = Errno(4)  //    /* Callback routine requested an abort */
	ErrBusy os.Error = Errno(5)  //    /* The database file is locked */
	ErrLocked os.Error = Errno(6)  //    /* A table in the database is locked */
	ErrNoMem os.Error = Errno(7)  //    /* A malloc() failed */
	ErrReadOnly os.Error = Errno(8)  //    /* Attempt to write a readonly database */
	ErrInterrupt os.Error = Errno(9)  //    /* Operation terminated by sqlite3_interrupt()*/
	ErrIOErr os.Error = Errno(10)  //    /* Some kind of disk I/O error occurred */
	ErrCorrupt os.Error = Errno(11)  //    /* The database disk image is malformed */
	ErrFull os.Error = Errno(13)  //    /* Insertion failed because database is full */
	ErrCantOpen os.Error = Errno(14)  //    /* Unable to open the database file */
	ErrEmpty os.Error = Errno(16)  //    /* Database is empty */
	ErrSchema os.Error = Errno(17)  //    /* The database schema changed */
	ErrTooBig os.Error = Errno(18)  //    /* String or BLOB exceeds size limit */
	ErrConstraint os.Error = Errno(19)  //    /* Abort due to constraint violation */
	ErrMismatch os.Error = Errno(20)  //    /* Data type mismatch */
	ErrMisuse os.Error = Errno(21)  //    /* Library used incorrectly */
	ErrNolfs os.Error = Errno(22)  //    /* Uses OS features not supported on host */
	ErrAuth os.Error = Errno(23)  //    /* Authorization denied */
	ErrFormat os.Error = Errno(24)  //    /* Auxiliary database format error */
	ErrRange os.Error = Errno(25)  //    /* 2nd parameter to sqlite3_bind out of range */
	ErrNotDB os.Error = Errno(26)  //    /* File opened that is not a database file */
	Row = Errno(100)  //   /* sqlite3_step() has another row ready */
	Done = Errno(101)  //   /* sqlite3_step() has finished executing */
)

var errText = map[Errno]string {
	1: "SQL error or missing database",
	2: "Internal logic error in SQLite",
	3: "Access permission denied",
	4: "Callback routine requested an abort",
	5: "The database file is locked",
	6: "A table in the database is locked",
	7: "A malloc() failed",
	8: "Attempt to write a readonly database",
	9: "Operation terminated by sqlite3_interrupt()*/",
	10: "Some kind of disk I/O error occurred",
	11: "The database disk image is malformed",
	12: "NOT USED. Table or record not found",
	13: "Insertion failed because database is full",
	14: "Unable to open the database file",
	15: "NOT USED. Database lock protocol error",
	16: "Database is empty",
	17: "The database schema changed",
	18: "String or BLOB exceeds size limit",
	19: "Abort due to constraint violation",
	20: "Data type mismatch",
	21: "Library used incorrectly",
	22: "Uses OS features not supported on host",
	23: "Authorization denied",
	24: "Auxiliary database format error",
	25: "2nd parameter to sqlite3_bind out of range",
	26: "File opened that is not a database file",
	100: "sqlite3_step() has another row ready",
	101: "sqlite3_step() has finished executing",
}

func (c *Conn) error(rv C.int) os.Error {
	if c == nil || c.db == nil {
		return os.NewError("nil sqlite database")
	}
	if rv == 0 {
		return nil
	}
	if rv == 21 {	// misuse
		return Errno(rv)
	}
	return os.NewError(Errno(rv).String() + ": " + C.GoString(C.sqlite3_errmsg(c.db)))
}

type Conn struct {
	db *C.sqlite3
}

func Version() string {
	p := C.sqlite3_libversion();
	return C.GoString(p);
}

func Open(filename string) (*Conn, os.Error) {
	if C.sqlite3_threadsafe() == 0 {
		return nil, os.NewError("sqlite library was not compiled for thread-safe operation")
	}

	var db *C.sqlite3
	name := C.CString(filename)
	defer C.free(unsafe.Pointer(name))
	rv := C.sqlite3_open_v2(name, &db,
		C.SQLITE_OPEN_FULLMUTEX |
		C.SQLITE_OPEN_READWRITE |
		C.SQLITE_OPEN_CREATE,
		nil)
	if rv != 0 {
		return nil, Errno(rv)
	}
	if db == nil {
		return nil, os.NewError("sqlite succeeded without returning a database")
	}
	return &Conn{db}, nil
}

func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, os.Error) {
	dname := C.CString(dstTable)
	sname := C.CString(srcTable)
	defer C.free(unsafe.Pointer(dname))
	defer C.free(unsafe.Pointer(sname))

	sb := C.sqlite3_backup_init(dst.db, dname, src.db, sname)
	if sb == nil {
		return nil, dst.error(C.sqlite3_errcode(dst.db))
	}
	return &Backup{sb, dst, src}, nil
}

type Backup struct {
	sb *C.sqlite3_backup
	dst, src *Conn
}

func (b *Backup) Step(npage int) os.Error {
	rv := C.sqlite3_backup_step(b.sb, C.int(npage))
	if rv == 0 || Errno(rv) == ErrBusy || Errno(rv) == ErrLocked {
		return nil
	}
	return Errno(rv)
}

type BackupStatus struct {
	Remaining int
	PageCount int
}

func (b *Backup) Status() BackupStatus {
	return BackupStatus{int(C.sqlite3_backup_remaining(b.sb)), int(C.sqlite3_backup_pagecount(b.sb))}
}

func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) os.Error {
	var err os.Error
	for {
		err = b.Step(npage)
		if err != nil {
			break
		}
		if c != nil {
			c <- b.Status()
		}
		time.Sleep(sleepNs)
	}
	return b.dst.error(C.sqlite3_errcode(b.dst.db))
}

func (b *Backup) Close() os.Error {
	if b.sb == nil {
		return os.EINVAL
	}
	C.sqlite3_backup_finish(b.sb)
	b.sb = nil
	return nil
}

func (c *Conn) Exec(cmd string, args ...interface{}) os.Error {
	s, err := c.Prepare(cmd)
	if err != nil {
		return err
	}
	defer s.Finalize()
	err = s.Exec(args...)
	if err != nil {
		return err
	}
	rv := C.sqlite3_step(s.stmt)
	if Errno(rv) != Done {
		return c.error(rv)
	}
	return nil
}

type Stmt struct {
	c *Conn
	stmt *C.sqlite3_stmt
	err os.Error
	t0 int64
	sql string
	args string
}

func (c *Conn) Prepare(cmd string) (*Stmt, os.Error) {
	if c == nil || c.db == nil {
		return nil, os.NewError("nil sqlite database")
	}
	cmdstr := C.CString(cmd)
	defer C.free(unsafe.Pointer(cmdstr))
	var stmt *C.sqlite3_stmt
	var tail *C.char
	rv := C.sqlite3_prepare_v2(c.db, cmdstr, C.int(len(cmd)+1), &stmt, &tail)
	if rv != 0 {
		return nil, c.error(rv)
	}
	return &Stmt{c: c, stmt: stmt, sql: cmd, t0: time.Nanoseconds()}, nil
}

func (s *Stmt) Exec(args ...interface{}) os.Error {
	s.args = fmt.Sprintf(" %v", []interface{}(args))
	rv := C.sqlite3_reset(s.stmt)
	if rv != 0 {
		return s.c.error(rv)
	}

	n := int(C.sqlite3_bind_parameter_count(s.stmt))
	if n != len(args) {
		return os.NewError(fmt.Sprintf("incorrect argument count for Stmt.Exec: have %d want %d", len(args), n))
	}

	for i, v := range args {
		var str string
		switch v := v.(type) {
		case []byte:
			var p *byte
			if len(v) > 0 {
				p = &v[0]
			}
			if rv := C.my_bind_blob(s.stmt, C.int(i+1), unsafe.Pointer(p), C.int(len(v))); rv != 0 {
				return s.c.error(rv)
			}
			continue

		case bool:
			if v {
				str = "1"
			} else {
				str = "0"
			}

		default:
			str = fmt.Sprint(v)
		}

		cstr := C.CString(str)
		rv := C.my_bind_text(s.stmt, C.int(i+1), cstr, C.int(len(str)))
		C.free(unsafe.Pointer(cstr))
		if rv != 0 {
			return s.c.error(rv)
		}
	}
	return nil
}

func (s *Stmt) Error() os.Error {
	return s.err
}

func (s *Stmt) Next() bool {
	rv := C.sqlite3_step(s.stmt)
	err := Errno(rv)
	if err == Row {
		return true
	}
	if err != Done {
		s.err = s.c.error(rv)
	}
	return false
}

func (s *Stmt) Scan(args ...interface{}) os.Error {
	n := int(C.sqlite3_column_count(s.stmt))
	if n != len(args) {
		return os.NewError(fmt.Sprintf("incorrect argument count for Stmt.Scan: have %d want %d", len(args), n))
	}

	for i, v := range args {
		n := C.sqlite3_column_bytes(s.stmt, C.int(i))
		p := C.sqlite3_column_blob(s.stmt, C.int(i))
		if p == nil && n > 0 {
			return os.NewError("got nil blob")
		}
		var data []byte
		if n > 0 {
			data = (*[1<<30]byte)(unsafe.Pointer(p))[0:n]
		}
		switch v := v.(type) {
		case *[]byte:
			*v = data
		case *string:
			*v = string(data)
		case *bool:
			*v = string(data) == "1"
		case *int:
			x, err := strconv.Atoi(string(data))
			if err != nil {
				return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String())
			}
			*v = x
		case *int64:
			x, err := strconv.Atoi64(string(data))
			if err != nil {
				return os.NewError("arg " + strconv.Itoa(i) + " as int64: " + err.String())
			}
			*v = x
		case *float64:
			x, err := strconv.Atof64(string(data))
			if err != nil {
				return os.NewError("arg " + strconv.Itoa(i) + " as float64: " + err.String())
			}
			*v = x
		default:
			return os.NewError("unsupported type in Scan: " + reflect.Typeof(v).String())
		}
	}
	return nil
}

func (s *Stmt) SQL() string {
	return s.sql + s.args
}

func (s *Stmt) Nanoseconds() int64 {
	return time.Nanoseconds() - s.t0
}

func (s *Stmt) Finalize() os.Error {
	rv := C.sqlite3_finalize(s.stmt)
	if rv != 0 {
		return s.c.error(rv)
	}
	return nil
}

func (c *Conn) Close() os.Error {
	if c == nil || c.db == nil {
		return os.NewError("nil sqlite database")
	}
	rv := C.sqlite3_close(c.db)
	if rv != 0 {
		return c.error(rv)
	}
	c.db = nil
	return nil
}
<commit_msg>add BusyTimeout<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package sqlite provides access to the SQLite library, version 3.
package sqlite

/*
#include <sqlite3.h>
#include <stdlib.h>

// These wrappers are necessary because SQLITE_TRANSIENT
// is a pointer constant, and cgo doesn't translate them correctly.
// The definition in sqlite3.h is:
//
// typedef void (*sqlite3_destructor_type)(void*);
// #define SQLITE_STATIC      ((sqlite3_destructor_type)0)
// #define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)

static int my_bind_text(sqlite3_stmt *stmt, int n, char *p, int np) {
	return sqlite3_bind_text(stmt, n, p, np, SQLITE_TRANSIENT);
}
static int my_bind_blob(sqlite3_stmt *stmt, int n, void *p, int np) {
	return sqlite3_bind_blob(stmt, n, p, np, SQLITE_TRANSIENT);
}

*/
import "C"

import (
	"fmt"
	"os"
	"reflect"
	"strconv"
	"unsafe"
	"time"
)

type Errno int

func (e Errno) String() string {
	s := errText[e]
	if s == "" {
		return fmt.Sprintf("errno %d", int(e))
	}
	return s
}

var (
	ErrError os.Error = Errno(1)  //    /* SQL error or missing database */
	ErrInternal os.Error = Errno(2)  //    /* Internal logic error in SQLite */
	ErrPerm os.Error = Errno(3)  //    /* Access permission denied */
	ErrAbort os.Error = Errno(4)  //    /* Callback routine requested an abort */
	ErrBusy os.Error = Errno(5)  //    /* The database file is locked */
	ErrLocked os.Error = Errno(6)  //    /* A table in the database is locked */
	ErrNoMem os.Error = Errno(7)  //    /* A malloc() failed */
	ErrReadOnly os.Error = Errno(8)  //    /* Attempt to write a readonly database */
	ErrInterrupt os.Error = Errno(9)  //    /* Operation terminated by sqlite3_interrupt()*/
	ErrIOErr os.Error = Errno(10)  //    /* Some kind of disk I/O error occurred */
	ErrCorrupt os.Error = Errno(11)  //    /* The database disk image is malformed */
	ErrFull os.Error = Errno(13)  //    /* Insertion failed because database is full */
	ErrCantOpen os.Error = Errno(14)  //    /* Unable to open the database file */
	ErrEmpty os.Error = Errno(16)  //    /* Database is empty */
	ErrSchema os.Error = Errno(17)  //    /* The database schema changed */
	ErrTooBig os.Error = Errno(18)  //    /* String or BLOB exceeds size limit */
	ErrConstraint os.Error = Errno(19)  //    /* Abort due to constraint violation */
	ErrMismatch os.Error = Errno(20)  //    /* Data type mismatch */
	ErrMisuse os.Error = Errno(21)  //    /* Library used incorrectly */
	ErrNolfs os.Error = Errno(22)  //    /* Uses OS features not supported on host */
	ErrAuth os.Error = Errno(23)  //    /* Authorization denied */
	ErrFormat os.Error = Errno(24)  //    /* Auxiliary database format error */
	ErrRange os.Error = Errno(25)  //    /* 2nd parameter to sqlite3_bind out of range */
	ErrNotDB os.Error = Errno(26)  //    /* File opened that is not a database file */
	Row = Errno(100)  //   /* sqlite3_step() has another row ready */
	Done = Errno(101)  //   /* sqlite3_step() has finished executing */
)

var errText = map[Errno]string {
	1: "SQL error or missing database",
	2: "Internal logic error in SQLite",
	3: "Access permission denied",
	4: "Callback routine requested an abort",
	5: "The database file is locked",
	6: "A table in the database is locked",
	7: "A malloc() failed",
	8: "Attempt to write a readonly database",
	9: "Operation terminated by sqlite3_interrupt()*/",
	10: "Some kind of disk I/O error occurred",
	11: "The database disk image is malformed",
	12: "NOT USED. Table or record not found",
	13: "Insertion failed because database is full",
	14: "Unable to open the database file",
	15: "NOT USED. Database lock protocol error",
	16: "Database is empty",
	17: "The database schema changed",
	18: "String or BLOB exceeds size limit",
	19: "Abort due to constraint violation",
	20: "Data type mismatch",
	21: "Library used incorrectly",
	22: "Uses OS features not supported on host",
	23: "Authorization denied",
	24: "Auxiliary database format error",
	25: "2nd parameter to sqlite3_bind out of range",
	26: "File opened that is not a database file",
	100: "sqlite3_step() has another row ready",
	101: "sqlite3_step() has finished executing",
}

func (c *Conn) error(rv C.int) os.Error {
	if c == nil || c.db == nil {
		return os.NewError("nil sqlite database")
	}
	if rv == 0 {
		return nil
	}
	if rv == 21 {	// misuse
		return Errno(rv)
	}
	return os.NewError(Errno(rv).String() + ": " + C.GoString(C.sqlite3_errmsg(c.db)))
}

type Conn struct {
	db *C.sqlite3
}

func Version() string {
	p := C.sqlite3_libversion();
	return C.GoString(p);
}

func Open(filename string) (*Conn, os.Error) {
	if C.sqlite3_threadsafe() == 0 {
		return nil, os.NewError("sqlite library was not compiled for thread-safe operation")
	}

	var db *C.sqlite3
	name := C.CString(filename)
	defer C.free(unsafe.Pointer(name))
	rv := C.sqlite3_open_v2(name, &db,
		C.SQLITE_OPEN_FULLMUTEX |
		C.SQLITE_OPEN_READWRITE |
		C.SQLITE_OPEN_CREATE,
		nil)
	if rv != 0 {
		return nil, Errno(rv)
	}
	if db == nil {
		return nil, os.NewError("sqlite succeeded without returning a database")
	}
	return &Conn{db}, nil
}

func NewBackup(dst *Conn, dstTable string, src *Conn, srcTable string) (*Backup, os.Error) {
	dname := C.CString(dstTable)
	sname := C.CString(srcTable)
	defer C.free(unsafe.Pointer(dname))
	defer C.free(unsafe.Pointer(sname))

	sb := C.sqlite3_backup_init(dst.db, dname, src.db, sname)
	if sb == nil {
		return nil, dst.error(C.sqlite3_errcode(dst.db))
	}
	return &Backup{sb, dst, src}, nil
}

type Backup struct {
	sb *C.sqlite3_backup
	dst, src *Conn
}

func (b *Backup) Step(npage int) os.Error {
	rv := C.sqlite3_backup_step(b.sb, C.int(npage))
	if rv == 0 || Errno(rv) == ErrBusy || Errno(rv) == ErrLocked {
		return nil
	}
	return Errno(rv)
}

type BackupStatus struct {
	Remaining int
	PageCount int
}

func (b *Backup) Status() BackupStatus {
	return BackupStatus{int(C.sqlite3_backup_remaining(b.sb)), int(C.sqlite3_backup_pagecount(b.sb))}
}

func (b *Backup) Run(npage int, sleepNs int64, c chan<- BackupStatus) os.Error {
	var err os.Error
	for {
		err = b.Step(npage)
		if err != nil {
			break
		}
		if c != nil {
			c <- b.Status()
		}
		time.Sleep(sleepNs)
	}
	return b.dst.error(C.sqlite3_errcode(b.dst.db))
}

func (b *Backup) Close() os.Error {
	if b.sb == nil {
		return os.EINVAL
	}
	C.sqlite3_backup_finish(b.sb)
	b.sb = nil
	return nil
}

func (c *Conn) BusyTimeout(ms int) os.Error {
	rv := C.sqlite3_busy_timeout(c.db, C.int(ms))
	if rv == 0 {
		return nil
	}
	return Errno(rv)
}

func (c *Conn) Exec(cmd string, args ...interface{}) os.Error {
	s, err := c.Prepare(cmd)
	if err != nil {
		return err
	}
	defer s.Finalize()
	err = s.Exec(args...)
	if err != nil {
		return err
	}
	rv := C.sqlite3_step(s.stmt)
	if Errno(rv) != Done {
		return c.error(rv)
	}
	return nil
}

type Stmt struct {
	c *Conn
	stmt *C.sqlite3_stmt
	err os.Error
	t0 int64
	sql string
	args string
}

func (c *Conn) Prepare(cmd string) (*Stmt, os.Error) {
	if c == nil || c.db == nil {
		return nil, os.NewError("nil sqlite database")
	}
	cmdstr := C.CString(cmd)
	defer C.free(unsafe.Pointer(cmdstr))
	var stmt *C.sqlite3_stmt
	var tail *C.char
	rv := C.sqlite3_prepare_v2(c.db, cmdstr, C.int(len(cmd)+1), &stmt, &tail)
	if rv != 0 {
		return nil, c.error(rv)
	}
	return &Stmt{c: c, stmt: stmt, sql: cmd, t0: time.Nanoseconds()}, nil
}

func (s *Stmt) Exec(args ...interface{}) os.Error {
	s.args = fmt.Sprintf(" %v", []interface{}(args))
	rv := C.sqlite3_reset(s.stmt)
	if rv != 0 {
		return s.c.error(rv)
	}

	n := int(C.sqlite3_bind_parameter_count(s.stmt))
	if n != len(args) {
		return os.NewError(fmt.Sprintf("incorrect argument count for Stmt.Exec: have %d want %d", len(args), n))
	}

	for i, v := range args {
		var str string
		switch v := v.(type) {
		case []byte:
			var p *byte
			if len(v) > 0 {
				p = &v[0]
			}
			if rv := C.my_bind_blob(s.stmt, C.int(i+1), unsafe.Pointer(p), C.int(len(v))); rv != 0 {
				return s.c.error(rv)
			}
			continue

		case bool:
			if v {
				str = "1"
			} else {
				str = "0"
			}

		default:
			str = fmt.Sprint(v)
		}

		cstr := C.CString(str)
		rv := C.my_bind_text(s.stmt, C.int(i+1), cstr, C.int(len(str)))
		C.free(unsafe.Pointer(cstr))
		if rv != 0 {
			return s.c.error(rv)
		}
	}
	return nil
}

func (s *Stmt) Error() os.Error {
	return s.err
}

func (s *Stmt) Next() bool {
	rv := C.sqlite3_step(s.stmt)
	err := Errno(rv)
	if err == Row {
		return true
	}
	if err != Done {
		s.err = s.c.error(rv)
	}
	return false
}

func (s *Stmt) Scan(args ...interface{}) os.Error {
	n := int(C.sqlite3_column_count(s.stmt))
	if n != len(args) {
		return os.NewError(fmt.Sprintf("incorrect argument count for Stmt.Scan: have %d want %d", len(args), n))
	}

	for i, v := range args {
		n := C.sqlite3_column_bytes(s.stmt, C.int(i))
		p := C.sqlite3_column_blob(s.stmt, C.int(i))
		if p == nil && n > 0 {
			return os.NewError("got nil blob")
		}
		var data []byte
		if n > 0 {
			data = (*[1<<30]byte)(unsafe.Pointer(p))[0:n]
		}
		switch v := v.(type) {
		case *[]byte:
			*v = data
		case *string:
			*v = string(data)
		case *bool:
			*v = string(data) == "1"
		case *int:
			x, err := strconv.Atoi(string(data))
			if err != nil {
				return os.NewError("arg " + strconv.Itoa(i) + " as int: " + err.String())
			}
			*v = x
		case *int64:
			x, err := strconv.Atoi64(string(data))
			if err != nil {
				return os.NewError("arg " + strconv.Itoa(i) + " as int64: " + err.String())
			}
			*v = x
		case *float64:
			x, err := strconv.Atof64(string(data))
			if err != nil {
				return os.NewError("arg " + strconv.Itoa(i) + " as float64: " + err.String())
			}
			*v = x
		default:
			return os.NewError("unsupported type in Scan: " + reflect.Typeof(v).String())
		}
	}
	return nil
}

func (s *Stmt) SQL() string {
	return s.sql + s.args
}

func (s *Stmt) Nanoseconds() int64 {
	return time.Nanoseconds() - s.t0
}

func (s *Stmt) Finalize() os.Error {
	rv := C.sqlite3_finalize(s.stmt)
	if rv != 0 {
		return s.c.error(rv)
	}
	return nil
}

func (c *Conn) Close() os.Error {
	if c == nil || c.db == nil {
		return os.NewError("nil sqlite database")
	}
	rv := C.sqlite3_close(c.db)
	if rv != 0 {
		return c.error(rv)
	}
	c.db = nil
	return nil
}
<|endoftext|>


<commit_before>/*
 * gomacro - A Go interpreter with Lisp-like macros
 *
 * Copyright (C) 2017-2018 Massimiliano Ghilardi
 *
 *     This Source Code Form is subject to the terms of the Mozilla Public
 *     License, v. 2.0. If a copy of the MPL was not distributed with this
 *     file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 *
 * a_package.go
 *
 *  Created on: Feb 28, 2017
 *      Author: Massimiliano Ghilardi
 */

package imports

import (
	. "reflect"

	go1_11 "github.com/cosmos72/gomacro/imports/go1_11"
	syscall "github.com/cosmos72/gomacro/imports/syscall"
	thirdparty "github.com/cosmos72/gomacro/imports/thirdparty"
)

type PackageUnderlying = struct { // unnamed
	Binds   map[string]Value
	Types   map[string]Type
	Proxies map[string]Type
	// Untypeds contains a string representation of untyped constants,
	// stored without loss of precision
	Untypeds map[string]string
	// Wrappers is the list of wrapper methods for named types.
	// Stored explicitly because reflect package cannot distinguish
	// between explicit methods and wrapper methods for embedded fields
	Wrappers map[string][]string
}

type Package PackageUnderlying // named, can have methods

type PackageMap map[string]Package // named, can have methods

var Packages = make(PackageMap)

// reflection: allow interpreted code to import "github.com/cosmos72/gomacro/imports"
func init() {
	Packages["github.com/cosmos72/gomacro/imports"] = Package{
		Binds: map[string]Value{
			"Packages": ValueOf(&Packages).Elem(),
		},
		Types: map[string]Type{
			"Package": TypeOf((*Package)(nil)).Elem(),
		},
	}
	Packages.Merge(go1_11.Packages)
	Packages.Merge(syscall.Packages)
	Packages.Merge(thirdparty.Packages)
}

func (pkgs PackageMap) Merge(srcs map[string]PackageUnderlying) {
	// exploit the fact that maps are actually handles
	for path, src := range srcs {
		pkgs.MergePackage(path, src)
	}
}

func (pkgs PackageMap) MergePackage(path string, src PackageUnderlying) {
	// exploit the fact that maps are actually handles
	pkg, ok := pkgs[path]
	if ok {
		pkg.Merge(src)
	} else {
		pkg = Package(src)
		pkg.LazyInit()
		pkgs[path] = pkg
	}
}

func (pkg *Package) LazyInit() {
	if pkg.Binds == nil {
		pkg.Binds = make(map[string]Value)
	}
	if pkg.Types == nil {
		pkg.Types = make(map[string]Type)
	}
	if pkg.Proxies == nil {
		pkg.Proxies = make(map[string]Type)
	}
	if pkg.Untypeds == nil {
		pkg.Untypeds = make(map[string]string)
	}
	if pkg.Wrappers == nil {
		pkg.Wrappers = make(map[string][]string)
	}
}

func (dst Package) Merge(src PackageUnderlying) {
	// exploit the fact that maps are actually handles
	for k, v := range src.Binds {
		dst.Binds[k] = v
	}
	for k, v := range src.Types {
		dst.Types[k] = v
	}
	for k, v := range src.Proxies {
		dst.Proxies[k] = v
	}
	for k, v := range src.Untypeds {
		dst.Untypeds[k] = v
	}
	for k, v := range src.Wrappers {
		dst.Wrappers[k] = v
	}
}
<commit_msg>add missing types to imports/a_package.go<commit_after>/*
 * gomacro - A Go interpreter with Lisp-like macros
 *
 * Copyright (C) 2017-2018 Massimiliano Ghilardi
 *
 *     This Source Code Form is subject to the terms of the Mozilla Public
 *     License, v. 2.0. If a copy of the MPL was not distributed with this
 *     file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 *
 * a_package.go
 *
 *  Created on: Feb 28, 2017
 *      Author: Massimiliano Ghilardi
 */

package imports

import (
	. "reflect"

	go1_11 "github.com/cosmos72/gomacro/imports/go1_11"
	syscall "github.com/cosmos72/gomacro/imports/syscall"
	thirdparty "github.com/cosmos72/gomacro/imports/thirdparty"
)

type PackageUnderlying = struct { // unnamed
	Binds   map[string]Value
	Types   map[string]Type
	Proxies map[string]Type
	// Untypeds contains a string representation of untyped constants,
	// stored without loss of precision
	Untypeds map[string]string
	// Wrappers is the list of wrapper methods for named types.
	// Stored explicitly because reflect package cannot distinguish
	// between explicit methods and wrapper methods for embedded fields
	Wrappers map[string][]string
}

type Package PackageUnderlying // named, can have methods

type PackageMap map[string]Package // named, can have methods

var Packages = make(PackageMap)

// reflection: allow interpreted code to import "github.com/cosmos72/gomacro/imports"
func init() {
	Packages["github.com/cosmos72/gomacro/imports"] = Package{
		Binds: map[string]Value{
			"Packages": ValueOf(&Packages).Elem(),
		},
		Types: map[string]Type{
			"Package":           TypeOf((*Package)(nil)).Elem(),
			"PackageMap":        TypeOf((*PackageMap)(nil)).Elem(),
			"PackageUnderlying": TypeOf((*PackageUnderlying)(nil)).Elem(),
		},
	}
	Packages.Merge(go1_11.Packages)
	Packages.Merge(syscall.Packages)
	Packages.Merge(thirdparty.Packages)
}

func (pkgs PackageMap) Merge(srcs map[string]PackageUnderlying) {
	// exploit the fact that maps are actually handles
	for path, src := range srcs {
		pkgs.MergePackage(path, src)
	}
}

func (pkgs PackageMap) MergePackage(path string, src PackageUnderlying) {
	// exploit the fact that maps are actually handles
	pkg, ok := pkgs[path]
	if ok {
		pkg.Merge(src)
	} else {
		pkg = Package(src)
		pkg.LazyInit()
		pkgs[path] = pkg
	}
}

func (pkg *Package) LazyInit() {
	if pkg.Binds == nil {
		pkg.Binds = make(map[string]Value)
	}
	if pkg.Types == nil {
		pkg.Types = make(map[string]Type)
	}
	if pkg.Proxies == nil {
		pkg.Proxies = make(map[string]Type)
	}
	if pkg.Untypeds == nil {
		pkg.Untypeds = make(map[string]string)
	}
	if pkg.Wrappers == nil {
		pkg.Wrappers = make(map[string][]string)
	}
}

func (dst *Package) Merge(src PackageUnderlying) {
	for k, v := range src.Binds {
		dst.Binds[k] = v
	}
	for k, v := range src.Types {
		dst.Types[k] = v
	}
	for k, v := range src.Proxies {
		dst.Proxies[k] = v
	}
	for k, v := range src.Untypeds {
		dst.Untypeds[k] = v
	}
	for k, v := range src.Wrappers {
		dst.Wrappers[k] = v
	}
}
<|endoftext|>


<commit_before>package multiconfig

import "testing"

type (
	Server struct {
		Name     string
		Port     int
		Enabled  bool
		Users    []string
		Postgres Postgres
	}

	// Postgres holds Postgresql database related configuration
	Postgres struct {
		Enabled           bool
		Port              int
		Hosts             []string
		DBName            string
		AvailabilityRatio float64
	}
)

var (
	testTOML = "testdata/config.toml"
	testJSON = "testdata/config.json"
)

func TestNewWithPath(t *testing.T) {
	var _ Loader = NewWithPath(testTOML)
}

func TestLoad(t *testing.T) {
	m := NewWithPath(testTOML)

	s := new(Server)
	if err := m.Load(s); err != nil {
		t.Error(err)
	}

	if s.Name != "Koding" {
		t.Errorf("Name value is wrong: %s, want: %s", s.Name, "Koding")
	}

	if s.Port != 6060 {
		t.Errorf("Port value is wrong: %s, want: %s", s.Port, 6060)
	}

	if !s.Enabled {
		t.Errorf("Enabled value is wrong: %s, want: %s", s.Enabled, true)
	}

	if len(s.Users) != 2 {
		t.Errorf("Users value is wrong: %s, want: %s", len(s.Users), 2)
	}
}

func TestTomlEmbeddedStruct(t *testing.T) {
	m := NewWithPath(testTOML)

	s := &Server{}
	if err := m.Load(s); err != nil {
		t.Error(err)
	}

	testEmbededStruct(t, s)
}

func TestJSONEmbeddedStruct(t *testing.T) {
	m := NewWithPath(testJSON)

	s := &Server{}
	if err := m.Load(s); err != nil {
		t.Error(err)
	}

	testEmbededStruct(t, s)
}

func testEmbededStruct(t *testing.T, s *Server) {
	// Explicitly state that Enabled should be true, no need to check
	// `x == true` infact.
	if s.Postgres.Enabled != true {
		t.Error("Enabled should be true")
	}

	port := 5432
	if s.Postgres.Port != port {
		t.Errorf("Port value is wrong: %s, want: %s", s.Postgres.Port, port)
	}

	dbName := "configdb"
	if s.Postgres.DBName != dbName {
		t.Errorf("DBName is wrong: %s, want: %s", s.Postgres.DBName, dbName)
	}

	var availabilityRatio float64 = 8.23
	if s.Postgres.AvailabilityRatio != availabilityRatio {
		t.Errorf("AvailabilityRatio is wrong: %d, want: %d", s.Postgres.AvailabilityRatio, availabilityRatio)
	}

	hosts := []string{"192.168.2.1", "192.168.2.2", "192.168.2.3"}
	if len(s.Postgres.Hosts) != 3 {
		// do not continue testing if this fails, because others is depending on this test
		t.Fatalf("Hosts len is wrong: %v, want: %v", s.Postgres.Hosts, hosts)
	}

	for i, host := range hosts {
		if s.Postgres.Hosts[i] != host {
			t.Fatalf("Hosts number %d is wrong: %v, want: %v", i, s.Postgres.Hosts[i], host)
		}
	}
}
<commit_msg>Multiconfig: pass default value as a function parameter<commit_after>package multiconfig

import "testing"

type (
	Server struct {
		Name     string
		Port     int
		Enabled  bool
		Users    []string
		Postgres Postgres
	}

	// Postgres holds Postgresql database related configuration
	Postgres struct {
		Enabled           bool
		Port              int
		Hosts             []string
		DBName            string
		AvailabilityRatio float64
	}
)

var (
	testTOML = "testdata/config.toml"
	testJSON = "testdata/config.json"
)

func getDefaultServer() *Server {
	return &Server{
		Name:    "koding",
		Port:    6060,
		Enabled: true,
		Postgres: Postgres{
			Enabled:           true,
			Port:              5432,
			Hosts:             []string{"192.168.2.1", "192.168.2.2", "192.168.2.3"},
			DBName:            "configdb",
			AvailabilityRatio: 8.23,
		},
	}
}

func TestNewWithPath(t *testing.T) {
	var _ Loader = NewWithPath(testTOML)
}

func TestLoad(t *testing.T) {
	m := NewWithPath(testTOML)

	s := new(Server)
	if err := m.Load(s); err != nil {
		t.Error(err)
	}

	if s.Name != "Koding" {
		t.Errorf("Name value is wrong: %s, want: %s", s.Name, "Koding")
	}

	if s.Port != 6060 {
		t.Errorf("Port value is wrong: %s, want: %s", s.Port, 6060)
	}

	if !s.Enabled {
		t.Errorf("Enabled value is wrong: %s, want: %s", s.Enabled, true)
	}

	if len(s.Users) != 2 {
		t.Errorf("Users value is wrong: %s, want: %s", len(s.Users), 2)
	}
}

func TestTomlEmbeddedStruct(t *testing.T) {
	m := NewWithPath(testTOML)

	s := &Server{}
	if err := m.Load(s); err != nil {
		t.Error(err)
	}

	testEmbededStruct(t, s, getDefaultServer())
}

func TestJSONEmbeddedStruct(t *testing.T) {
	m := NewWithPath(testJSON)

	s := &Server{}
	if err := m.Load(s); err != nil {
		t.Error(err)
	}

	testEmbededStruct(t, s, getDefaultServer())
}

func testEmbededStruct(t *testing.T, s *Server) {

func testEmbededStruct(t *testing.T, s *Server, d *Server) {
	// Explicitly state that Enabled should be true, no need to check
	// `x == true` infact.
	if s.Postgres.Enabled != d.Postgres.Enabled {
		t.Error("Enabled is wrong %t, want: %t", s.Postgres.Enabled, d.Postgres.Enabled)
	}

	if s.Postgres.Port != d.Postgres.Port {
		t.Errorf("Port value is wrong: %s, want: %s", s.Postgres.Port, d.Postgres.Port)
	}

	if s.Postgres.DBName != d.Postgres.DBName {
		t.Errorf("DBName is wrong: %s, want: %s", s.Postgres.DBName, d.Postgres.DBName)
	}

	if s.Postgres.AvailabilityRatio != d.Postgres.AvailabilityRatio {
		t.Errorf("AvailabilityRatio is wrong: %d, want: %d", s.Postgres.AvailabilityRatio, d.Postgres.AvailabilityRatio)
	}

	if len(s.Postgres.Hosts) != len(d.Postgres.Hosts) {
		// do not continue testing if this fails, because others is depending on this test
		t.Fatalf("Hosts len is wrong: %v, want: %v", s.Postgres.Hosts, d.Postgres.Hosts)
	}

	for i, host := range d.Postgres.Hosts {
		if s.Postgres.Hosts[i] != host {
			t.Fatalf("Hosts number %d is wrong: %v, want: %v", i, s.Postgres.Hosts[i], host)
		}
	}
}
<|endoftext|>


<commit_before>package ilium

import "encoding/json"
import "errors"
import "io/ioutil"

func rawParseConfig(inputPath string) (
	config map[string]interface{}, err error) {
	configBytes, err := ioutil.ReadFile(inputPath)
	if err != nil {
		return
	}
	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		config = nil
		return
	}
	return
}

func processIncludes(config interface{}, depth int) (
	newConfig interface{}, err error) {
	if depth >= 10 {
		err = errors.New("Include depth limit exceeded")
		return
	}

	switch typedConfig := config.(type) {
	case map[string]interface{}:
		if includeConfig, ok := typedConfig["_include"]; ok {
			includePath := includeConfig.(string)
			newConfig, err = parseConfigRecursively(
				includePath, depth+1)
			if err != nil {
				newConfig = nil
			}
			return
		}

		for k, v := range typedConfig {
			v, err = processIncludes(v, depth)
			if err != nil {
				return
			}
			typedConfig[k] = v
		}

	case []interface{}:
		for i, v := range typedConfig {
			v, err = processIncludes(v, depth)
			if err != nil {
				return
			}
			typedConfig[i] = v
		}
	}

	newConfig = config
	return
}

func parseConfigRecursively(inputPath string, depth int) (
	config map[string]interface{}, err error) {
	config, err = rawParseConfig(inputPath)
	if err != nil {
		return
	}
	var processedConfig interface{}
	processedConfig, err = processIncludes(config, 0)
	if err != nil {
		config = nil
		return
	}
	config = processedConfig.(map[string]interface{})
	return
}

func ParseConfig(inputPath string) (config map[string]interface{}, err error) {
	return parseConfigRecursively(inputPath, 0)
}
<commit_msg>Process relative paths for include directives<commit_after>package ilium

import "encoding/json"
import "errors"
import "io/ioutil"
import "path/filepath"

func rawParseConfig(inputPath string) (
	config map[string]interface{}, err error) {
	configBytes, err := ioutil.ReadFile(inputPath)
	if err != nil {
		return
	}
	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		config = nil
		return
	}
	return
}

func processIncludes(dir string, config interface{}, depth int) (
	newConfig interface{}, err error) {
	if depth >= 10 {
		err = errors.New("Include depth limit exceeded")
		return
	}

	switch typedConfig := config.(type) {
	case map[string]interface{}:
		if includeConfig, ok := typedConfig["_include"]; ok {
			includePath := filepath.Join(
				dir, includeConfig.(string))
			newConfig, err = parseConfigRecursively(
				includePath, depth+1)
			if err != nil {
				newConfig = nil
			}
			return
		}

		for k, v := range typedConfig {
			v, err = processIncludes(dir, v, depth)
			if err != nil {
				return
			}
			typedConfig[k] = v
		}

	case []interface{}:
		for i, v := range typedConfig {
			v, err = processIncludes(dir, v, depth)
			if err != nil {
				return
			}
			typedConfig[i] = v
		}
	}

	newConfig = config
	return
}

func parseConfigRecursively(inputPath string, depth int) (
	config map[string]interface{}, err error) {
	config, err = rawParseConfig(inputPath)
	if err != nil {
		return
	}
	var processedConfig interface{}
	var absPath string
	absPath, err = filepath.Abs(inputPath)
	if err != nil {
		config = nil
		return
	}
	dir := filepath.Dir(absPath)
	processedConfig, err = processIncludes(dir, config, 0)
	if err != nil {
		config = nil
		return
	}
	config = processedConfig.(map[string]interface{})
	return
}

func ParseConfig(inputPath string) (config map[string]interface{}, err error) {
	return parseConfigRecursively(inputPath, 0)
}
<|endoftext|>