<commit_before>package tracing

import (
	"errors"
	"fmt"
	"io"
	"strings"

	opentracing "github.com/opentracing/opentracing-go"
	"github.com/sirupsen/logrus"
	jeagerConf "github.com/uber/jaeger-client-go/config"
)

type Tracer struct {
	ServiceName  string
	Provider     string
	Logger       logrus.FieldLogger
	JaegerConfig *JaegerConfig

	tracer opentracing.Tracer
	closer io.Closer
}

type JaegerConfig struct {
	LocalAgentHostPort string
	SamplerType        string
	SamplerValue       float64
	SamplerServerUrl   string
}

func (t *Tracer) Setup() error {
	switch strings.ToLower(t.Provider) {
	case "jaeger":
		jc := jeagerConf.Configuration{
			Sampler: &jeagerConf.SamplerConfig{
				SamplingServerURL: t.JaegerConfig.SamplerServerUrl,
				Type:              t.JaegerConfig.SamplerType,
				Param:             t.JaegerConfig.SamplerValue,
			},
			Reporter: &jeagerConf.ReporterConfig{
				LocalAgentHostPort: t.JaegerConfig.LocalAgentHostPort,
			},
		}

		closer, err := jc.InitGlobalTracer(
			t.ServiceName,
		)

		if err != nil {
			return err
		}

		t.closer = closer
		t.tracer = opentracing.GlobalTracer()
		t.Logger.Infof("Jaeger tracer configured!")
	case "":
		t.Logger.Infof("No tracer configured - skipping tracing setup")
	default:
		return errors.New(fmt.Sprintf("unknown tracer: %s", t.Provider))
	}
	return nil
}

func (t *Tracer) IsLoaded() bool {
	if t == nil || t.tracer == nil {
		return false
	}
	return true
}

func (t *Tracer) Close() {
	if t.closer != nil {
		err := t.closer.Close()
		if err != nil {
			t.Logger.Warn(err)
		}
	}
}

func HelpMessage() string {
	return `- TRACING_PROVIDER: Set this to the tracing backend you wish to use.

	Supported tracing backends: [jaeger]

	Example: TRACING_PROVIDER=jaeger

- TRACING_PROVIDER_JAEGER_SAMPLING_SERVER_URL: The address of jaeger-agent's HTTP sampling server

	Example: TRACING_PROVIDER_JAEGER_SAMPLING_SERVER_URL=http://localhost:5778/sampling

- TRACING_PROVIDER_JAEGER_SAMPLING_TYPE: The type of the sampler you want to use

	Supported values: [const, probabilistic, ratelimiting]

	Default: const

	Example: TRACING_PROVIDER_JAEGER_SAMPLING_TYPE=const

- TRACING_PROVIDER_JAEGER_SAMPLING_VALUE: The value passed to the sampler type that has been configured.

	Supported values: This is dependant on the sampling strategy used:
		- const: 0 or 1 (all or nothing)
		- rateLimiting: a constant rate (e.g. setting this to 3 will sample requests with the rate of 3 traces per second)
		- probabilistic: a value between 0..1

	Example: TRACING_PROVIDER_JAEGER_SAMPLING_VALUE=1

- TRACING_PROVIDER_JAEGER_LOCAL_AGENT_ADDRESS: The address of the jaeger-agent where spans should be sent to

	Example: TRACING_PROVIDER_JAEGER_LOCAL_AGENT_ADDRESS=127.0.0.1:6831

- TRACING_SERVICE_NAME: Specifies the service name to use on the tracer.

	Default: ORY Hydra

	Example: TRACING_SERVICE_NAME="ORY Hydra"
`
}
<commit_msg>driver: Support default jaeger environment variables (#1442)<commit_after>package tracing

import (
	"io"
	"strings"

	opentracing "github.com/opentracing/opentracing-go"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
	jeagerConf "github.com/uber/jaeger-client-go/config"
)

type Tracer struct {
	ServiceName  string
	Provider     string
	Logger       logrus.FieldLogger
	JaegerConfig *JaegerConfig

	tracer opentracing.Tracer
	closer io.Closer
}

type JaegerConfig struct {
	LocalAgentHostPort string
	SamplerType        string
	SamplerValue       float64
	SamplerServerUrl   string
}

func (t *Tracer) Setup() error {
	switch strings.ToLower(t.Provider) {
	case "jaeger":
		jc, err := jeagerConf.FromEnv()

		if err != nil {
			return err
		}

		if t.JaegerConfig.SamplerServerUrl != "" {
			jc.Sampler.SamplingServerURL = t.JaegerConfig.SamplerServerUrl
		}

		if t.JaegerConfig.SamplerType != "" {
			jc.Sampler.Type = t.JaegerConfig.SamplerType
		}

		if t.JaegerConfig.SamplerValue != 0 {
			jc.Sampler.Param = t.JaegerConfig.SamplerValue
		}

		if t.JaegerConfig.LocalAgentHostPort != "" {
			jc.Reporter.LocalAgentHostPort = t.JaegerConfig.LocalAgentHostPort
		}

		closer, err := jc.InitGlobalTracer(
			t.ServiceName,
		)

		if err != nil {
			return err
		}

		t.closer = closer
		t.tracer = opentracing.GlobalTracer()
		t.Logger.Infof("Jaeger tracer configured!")
	case "":
		t.Logger.Infof("No tracer configured - skipping tracing setup")
	default:
		return errors.Errorf("unknown tracer: %s", t.Provider)
	}
	return nil
}

func (t *Tracer) IsLoaded() bool {
	if t == nil || t.tracer == nil {
		return false
	}
	return true
}

func (t *Tracer) Close() {
	if t.closer != nil {
		err := t.closer.Close()
		if err != nil {
			t.Logger.Warn(err)
		}
	}
}

func HelpMessage() string {
	return `- TRACING_PROVIDER: Set this to the tracing backend you wish to use.

	Supported tracing backends: [jaeger]

	Example: TRACING_PROVIDER=jaeger

- TRACING_PROVIDER_JAEGER_SAMPLING_SERVER_URL: The address of jaeger-agent's HTTP sampling server

	Example: TRACING_PROVIDER_JAEGER_SAMPLING_SERVER_URL=http://localhost:5778/sampling

- TRACING_PROVIDER_JAEGER_SAMPLING_TYPE: The type of the sampler you want to use

	Supported values: [const, probabilistic, ratelimiting]

	Default: const

	Example: TRACING_PROVIDER_JAEGER_SAMPLING_TYPE=const

- TRACING_PROVIDER_JAEGER_SAMPLING_VALUE: The value passed to the sampler type that has been configured.

	Supported values: This is dependant on the sampling strategy used:
		- const: 0 or 1 (all or nothing)
		- rateLimiting: a constant rate (e.g. setting this to 3 will sample requests with the rate of 3 traces per second)
		- probabilistic: a value between 0..1

	Example: TRACING_PROVIDER_JAEGER_SAMPLING_VALUE=1

- TRACING_PROVIDER_JAEGER_LOCAL_AGENT_ADDRESS: The address of the jaeger-agent where spans should be sent to

	Example: TRACING_PROVIDER_JAEGER_LOCAL_AGENT_ADDRESS=127.0.0.1:6831

- TRACING_SERVICE_NAME: Specifies the service name to use on the tracer.

	Default: ORY Hydra

	Example: TRACING_SERVICE_NAME="ORY Hydra"
`
}
<|endoftext|>


<commit_before>package translate

import (
	"bytes"
	"fmt"
	gt "github.com/Sam-Izdat/pogo/deps/gettext"
	spec "github.com/Sam-Izdat/pogo/gtspec"
	"io/ioutil"
	"path/filepath"
	"strings"
)

// Translator delivers translation methods for a particular locale.
// It is exported for reference, but the New constructor should be
// used to initialize every translator.
type Translator struct {
	Locale string
	Ctrl   POGOCtrl
}

type collection map[string]gt.Catalog

// POGOCtrl is a configured handler for constructing translators
type POGOCtrl struct {
	o        spec.Config
	Catalogs collection
}

var LangDefault string
var LangsSupported = map[string]bool{}

// LoadCfg takes the path of the project directory
// (relative to $GOPATH/src/) containing the POGO.toml
// configuration file and loads the configuration variables.
// Normally, this will be the main directory of your package.
func LoadCfg(path string) POGOCtrl {
	var err error
	o, err := spec.LoadOptionsGOPATH(path)
	if err != nil {
		panic(err)
	}
	LangDefault = o.General.Targets[0]
	for _, v := range o.General.Targets {
		LangsSupported[v] = true
	}
	return POGOCtrl{o, make(collection)}
}

// New takes a locale and creates a new translator
func (p POGOCtrl) New(locale string) Translator {
	if p.o.General.ProjectFN == "" {
		panic("no pogo configuration loaded")
	}
	if supported, ok := LangsSupported[locale]; !ok || !supported {
		locale = LangDefault
	}
	p.readMo(locale)
	return Translator{locale, p}
}

func (p *POGOCtrl) readMo(locale string) {
	if _, ok := p.Catalogs[locale]; ok {
		return
	}
	fn := strings.Join([]string{p.o.General.ProjectFN, ".", locale, ".mo"}, "")
	path := filepath.Join(p.o.General.DirLocale, locale, p.o.General.DirMessages, fn)
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	c := gt.NewCatalog()
	if err := c.ReadMo(bytes.NewReader(data)); err != nil {
		panic(err)
	}
	p.Catalogs[locale] = *c
}

// G translates a string. The first argument must be
// the string to be translated. Any subsequent arguments
// will be translated, if possible, and considered arguments
// for sprintf.
func (t Translator) G(input ...interface{}) string {
	if len(input) < 1 {
		return ""
	}
	id := input[0].(string)

	// translate chain of remaining string inputs
	for k, v := range input[1:] {
		if s, ok := v.(string); ok {
			input[k+1] = t.G(s)
		}
	}

	c := t.Ctrl.Catalogs[t.Locale]
	if msg, ok := c.Msgs[id]; ok {
		if text := msg.Str; text != nil {
			if len(input) < 2 {
				return string(text)
			}
			return fmt.Sprintf(string(text), input[1:]...)
		}
	}

	if len(input) == 1 {
		return id
	} else {
		return fmt.Sprintf(input[0].(string), input[1:]...)
	}
}

// NG translates and pluralizes a string, according to
// a language's pluralization rules, if the quantity
// calls for a plural form. The first argument must
// be the singular form of the string to be translated;
// the second must be the plural form; the *last* argument
// must be the quantity; any other arguments preceding it
// will be translated, if possible, and considered arguments
// for sprintf.
func (t Translator) NG(input ...interface{}) string {
	if len(input) < 3 {
		return ""
	}
	ct := input[len(input)-1].(int)

	// translate chain of remaining string inputs
	for k, v := range input[2:] {
		if s, ok := v.(string); ok {
			input[k+2] = t.G(s)
		}
	}

	idx, err := spec.GetPluralIdx(t.Locale, ct)
	if err == nil {
		c := t.Ctrl.Catalogs[t.Locale]
		if msg, ok := c.Msgs[input[0].(string)]; ok {
			if text := msg.StrPlural[idx]; text != nil {
				if len(input) < 3 {
					return fmt.Sprintf(string(text), ct)
				}
				return fmt.Sprintf(string(text), input[2:]...)
			}
		}
	}

	if ct == 1 {
		return fmt.Sprintf(input[0].(string), input[2:]...)
	} else {
		return fmt.Sprintf(input[1].(string), input[2:]...)
	}
}

// PG translates a string with context/disambiguation. The first argument
// must be the context; the second must be the string to be translated.
// Any subsequent arguments will be translated, if possible,
// and considered arguments for sprintf.
func (t Translator) PG(input ...interface{}) string {
	if len(input) < 2 {
		return ""
	}

	// translate chain of remaining string inputs
	for k, v := range input[2:] {
		if s, ok := v.(string); ok {
			input[k+2] = t.G(s)
		}
	}

	c := t.Ctrl.Catalogs[t.Locale]
	key := strings.Join([]string{input[0].(string), "\x04", input[1].(string)}, "")
	if msg, ok := c.Msgs[key]; ok {
		if text := msg.Str; text != nil {
			if len(input) < 3 {
				return string(text)
			}
			return fmt.Sprintf(string(text), input[2:]...)
		}
	}
	return fmt.Sprintf(input[1].(string), input[2:]...)
}

// NPG translates a string with context, and pluralizes it,
// according to a language's pluralization rules, if the
// quantity calls for a plural form. The first argument must
// be the context, the second must be the singular form
// of the string to be translated; the third must be the plural form;
// the *last* argument must be the quantity; any other arguments
// preceding it will be translated, if possible, and considered
// arguments for sprintf.
func (t Translator) NPG(input ...interface{}) string {
	if len(input) < 4 {
		return ""
	}

	// translate chain of remaining string inputs
	for k, v := range input[3:] {
		if s, ok := v.(string); ok {
			input[k+3] = t.G(s)
		}
	}

	ct := input[len(input)-1].(int)
	idx, err := spec.GetPluralIdx(t.Locale, ct)
	if err == nil {
		c := t.Ctrl.Catalogs[t.Locale]
		key := strings.Join([]string{input[0].(string), "\x04", input[1].(string)}, "")
		if msg, ok := c.Msgs[key]; ok {
			if text := msg.StrPlural[idx]; text != nil {
				if len(input) < 5 {
					return fmt.Sprintf(string(text), ct)
				}
				return fmt.Sprintf(string(text), input[3:]...)
			}
		}
	}

	if ct == 1 {
		return fmt.Sprintf(input[1].(string), input[3:]...)
	} else {
		return fmt.Sprintf(input[2].(string), input[3:]...)
	}
}
<commit_msg>Added NewQV() function which accepts a best-first slice of locales, presumably sorted by quality values<commit_after>package translate

import (
	"bytes"
	"fmt"
	gt "github.com/Sam-Izdat/pogo/deps/gettext"
	spec "github.com/Sam-Izdat/pogo/gtspec"
	"io/ioutil"
	"path/filepath"
	"strings"
)

// Translator delivers translation methods for a particular locale.
// It is exported for reference, but the New constructor should be
// used to initialize every translator.
type Translator struct {
	Locale string
	Ctrl   POGOCtrl
}

type collection map[string]gt.Catalog

// POGOCtrl is a configured handler for constructing translators
type POGOCtrl struct {
	o        spec.Config
	Catalogs collection
}

var LangDefault string
var LangsSupported = map[string]bool{}

// LoadCfg takes the path of the project directory
// (relative to $GOPATH/src/) containing the POGO.toml
// configuration file and loads the configuration variables.
// Normally, this will be the main directory of your package.
func LoadCfg(path string) POGOCtrl {
	var err error
	o, err := spec.LoadOptionsGOPATH(path)
	if err != nil {
		panic(err)
	}
	LangDefault = o.General.Targets[0]
	for _, v := range o.General.Targets {
		LangsSupported[v] = true
	}
	return POGOCtrl{o, make(collection)}
}

// New takes a locale string and creates a new translator
func (p POGOCtrl) New(locale string) Translator {
	if p.o.General.ProjectFN == "" {
		panic("no pogo configuration loaded")
	}
	if supported, ok := LangsSupported[locale]; !ok || !supported {
		locale = LangDefault
	}
	p.readMo(locale)
	return Translator{locale, p}
}

// NewQV takes a slice of locale strings, sorted by quality value and creates
// the best available translator, falling back on default (first) language if
// no match is found.
func (p POGOCtrl) NewQV(locales []string) Translator {
	if p.o.General.ProjectFN == "" {
		panic("no pogo configuration loaded")
	}
	var locale string
	for _, v := range locales {
		if supported, ok := LangsSupported[v]; ok && supported {
			locale = v
			break
		}
	}
	if locale == "" {
		locale = LangDefault
	}
	p.readMo(locale)
	return Translator{locale, p}
}

func (p *POGOCtrl) readMo(locale string) {
	if _, ok := p.Catalogs[locale]; ok {
		return
	}
	fn := strings.Join([]string{p.o.General.ProjectFN, ".", locale, ".mo"}, "")
	path := filepath.Join(p.o.General.DirLocale, locale, p.o.General.DirMessages, fn)
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	c := gt.NewCatalog()
	if err := c.ReadMo(bytes.NewReader(data)); err != nil {
		panic(err)
	}
	p.Catalogs[locale] = *c
}

// G translates a string. The first argument must be
// the string to be translated. Any subsequent arguments
// will be translated, if possible, and considered arguments
// for sprintf.
func (t Translator) G(input ...interface{}) string {
	if len(input) < 1 {
		return ""
	}
	id := input[0].(string)

	// translate chain of remaining string inputs
	for k, v := range input[1:] {
		if s, ok := v.(string); ok {
			input[k+1] = t.G(s)
		}
	}

	c := t.Ctrl.Catalogs[t.Locale]
	if msg, ok := c.Msgs[id]; ok {
		if text := msg.Str; text != nil {
			if len(input) < 2 {
				return string(text)
			}
			return fmt.Sprintf(string(text), input[1:]...)
		}
	}

	if len(input) == 1 {
		return id
	} else {
		return fmt.Sprintf(input[0].(string), input[1:]...)
	}
}

// NG translates and pluralizes a string, according to
// a language's pluralization rules, if the quantity
// calls for a plural form. The first argument must
// be the singular form of the string to be translated;
// the second must be the plural form; the *last* argument
// must be the quantity; any other arguments preceding it
// will be translated, if possible, and considered arguments
// for sprintf.
func (t Translator) NG(input ...interface{}) string {
	if len(input) < 3 {
		return ""
	}
	ct := input[len(input)-1].(int)

	// translate chain of remaining string inputs
	for k, v := range input[2:] {
		if s, ok := v.(string); ok {
			input[k+2] = t.G(s)
		}
	}

	idx, err := spec.GetPluralIdx(t.Locale, ct)
	if err == nil {
		c := t.Ctrl.Catalogs[t.Locale]
		if msg, ok := c.Msgs[input[0].(string)]; ok {
			if text := msg.StrPlural[idx]; text != nil {
				if len(input) < 3 {
					return fmt.Sprintf(string(text), ct)
				}
				return fmt.Sprintf(string(text), input[2:]...)
			}
		}
	}

	if ct == 1 {
		return fmt.Sprintf(input[0].(string), input[2:]...)
	} else {
		return fmt.Sprintf(input[1].(string), input[2:]...)
	}
}

// PG translates a string with context/disambiguation. The first argument
// must be the context; the second must be the string to be translated.
// Any subsequent arguments will be translated, if possible,
// and considered arguments for sprintf.
func (t Translator) PG(input ...interface{}) string {
	if len(input) < 2 {
		return ""
	}

	// translate chain of remaining string inputs
	for k, v := range input[2:] {
		if s, ok := v.(string); ok {
			input[k+2] = t.G(s)
		}
	}

	c := t.Ctrl.Catalogs[t.Locale]
	key := strings.Join([]string{input[0].(string), "\x04", input[1].(string)}, "")
	if msg, ok := c.Msgs[key]; ok {
		if text := msg.Str; text != nil {
			if len(input) < 3 {
				return string(text)
			}
			return fmt.Sprintf(string(text), input[2:]...)
		}
	}
	return fmt.Sprintf(input[1].(string), input[2:]...)
}

// NPG translates a string with context, and pluralizes it,
// according to a language's pluralization rules, if the
// quantity calls for a plural form. The first argument must
// be the context, the second must be the singular form
// of the string to be translated; the third must be the plural form;
// the *last* argument must be the quantity; any other arguments
// preceding it will be translated, if possible, and considered
// arguments for sprintf.
func (t Translator) NPG(input ...interface{}) string {
	if len(input) < 4 {
		return ""
	}

	// translate chain of remaining string inputs
	for k, v := range input[3:] {
		if s, ok := v.(string); ok {
			input[k+3] = t.G(s)
		}
	}

	ct := input[len(input)-1].(int)
	idx, err := spec.GetPluralIdx(t.Locale, ct)
	if err == nil {
		c := t.Ctrl.Catalogs[t.Locale]
		key := strings.Join([]string{input[0].(string), "\x04", input[1].(string)}, "")
		if msg, ok := c.Msgs[key]; ok {
			if text := msg.StrPlural[idx]; text != nil {
				if len(input) < 5 {
					return fmt.Sprintf(string(text), ct)
				}
				return fmt.Sprintf(string(text), input[3:]...)
			}
		}
	}

	if ct == 1 {
		return fmt.Sprintf(input[1].(string), input[3:]...)
	} else {
		return fmt.Sprintf(input[2].(string), input[3:]...)
	}
}
<|endoftext|>


<commit_before>// -*- Mode: Go; indent-tabs-mode: t -*-

/*
 * Copyright (C) 2015-2016 Canonical Ltd
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/jessevdk/go-flags"
)

type msgID struct {
	msgidPlural string
	comment     string
	fname       string
	line        int
	formatHint  string
}

var msgIDs map[string][]msgID

func formatComment(com string) string {
	out := ""
	for _, rawline := range strings.Split(com, "\n") {
		line := rawline
		line = strings.TrimPrefix(line, "//")
		line = strings.TrimPrefix(line, "/*")
		line = strings.TrimSuffix(line, "*/")
		line = strings.TrimSpace(line)
		if line != "" {
			out += fmt.Sprintf("#. %s\n", line)
		}
	}

	return out
}

func findCommentsForTranslation(fset *token.FileSet, f *ast.File, posCall token.Position) string {
	com := ""
	for _, cg := range f.Comments {
		// search for all comments in the previous line
		for i := len(cg.List) - 1; i >= 0; i-- {
			c := cg.List[i]

			posComment := fset.Position(c.End())
			//println(posCall.Line, posComment.Line, c.Text)
			if posCall.Line == posComment.Line+1 {
				posCall = posComment
				com = fmt.Sprintf("%s\n%s", c.Text, com)
			}
		}
	}

	// only return if we have a matching prefix
	formatedComment := formatComment(com)
	needle := fmt.Sprintf("#. %s", opts.AddCommentsTag)
	if !strings.HasPrefix(formatedComment, needle) {
		formatedComment = ""
	}

	return formatedComment
}

func constructValue(val interface{}) string {
	switch val.(type) {
	case *ast.BasicLit:
		return val.(*ast.BasicLit).Value
	// this happens for constructs like:
	//  gettext.Gettext("foo" + "bar")
	case *ast.BinaryExpr:
		// we only support string concat
		if val.(*ast.BinaryExpr).Op != token.ADD {
			return ""
		}
		left := constructValue(val.(*ast.BinaryExpr).X)
		// strip right " (or `)
		left = left[0 : len(left)-1]
		right := constructValue(val.(*ast.BinaryExpr).Y)
		// strip left " (or `)
		right = right[1:len(right)]
		return left + right
	default:
		panic(fmt.Sprintf("unknown type: %v", val))
	}
}

func inspectNodeForTranslations(fset *token.FileSet, f *ast.File, n ast.Node) bool {
	// FIXME: this assume we always have a "gettext.Gettext" style keyword
	l := strings.Split(opts.Keyword, ".")
	gettextSelector := l[0]
	gettextFuncName := l[1]

	l = strings.Split(opts.KeywordPlural, ".")
	gettextSelectorPlural := l[0]
	gettextFuncNamePlural := l[1]

	switch x := n.(type) {
	case *ast.CallExpr:
		if sel, ok := x.Fun.(*ast.SelectorExpr); ok {
			i18nStr := ""
			i18nStrPlural := ""
			if sel.Sel.Name == gettextFuncNamePlural && sel.X.(*ast.Ident).Name == gettextSelectorPlural {
				i18nStr = x.Args[0].(*ast.BasicLit).Value
				i18nStrPlural = x.Args[1].(*ast.BasicLit).Value
			}

			if sel.Sel.Name == gettextFuncName && sel.X.(*ast.Ident).Name == gettextSelector {
				i18nStr = constructValue(x.Args[0])
			}

			formatI18nStr := func(s string) string {
				if s == "" {
					return ""
				}
				// the "`" is special
				if s[0] == '`' {
					// replace inner " with \"
					s = strings.Replace(s, "\"", "\\\"", -1)
					// replace \n with \\n
					s = strings.Replace(s, "\n", "\\n", -1)
				}
				// strip leading and trailing " (or `)
				s = s[1 : len(s)-1]
				return s
			}

			// FIXME: too simplistic(?), no %% is considered
			formatHint := ""
			if strings.Contains(i18nStr, "%") || strings.Contains(i18nStrPlural, "%") {
				// well, not quite correct but close enough
				formatHint = "c-format"
			}

			if i18nStr != "" {
				msgidStr := formatI18nStr(i18nStr)
				posCall := fset.Position(n.Pos())
				msgIDs[msgidStr] = append(msgIDs[msgidStr], msgID{
					formatHint:  formatHint,
					msgidPlural: formatI18nStr(i18nStrPlural),
					fname:       posCall.Filename,
					line:        posCall.Line,
					comment:     findCommentsForTranslation(fset, f, posCall),
				})
			}
		}
	}

	return true
}

func processFiles(args []string) error {
	// go over the input files
	msgIDs = make(map[string][]msgID)

	fset := token.NewFileSet()
	for _, fname := range args {
		if err := processSingleGoSource(fset, fname); err != nil {
			return err
		}
	}

	return nil
}

func processSingleGoSource(fset *token.FileSet, fname string) error {
	fnameContent, err := ioutil.ReadFile(fname)
	if err != nil {
		panic(err)
	}

	// Create the AST by parsing src.
	f, err := parser.ParseFile(fset, fname, fnameContent, parser.ParseComments)
	if err != nil {
		panic(err)
	}

	ast.Inspect(f, func(n ast.Node) bool {
		return inspectNodeForTranslations(fset, f, n)
	})

	return nil
}

var formatTime = func() string {
	return time.Now().Format("2006-01-02 15:04-0700")
}

func writePotFile(out io.Writer) {

	header := fmt.Sprintf(`# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid   ""
msgstr  "Project-Id-Version: %s\n"
        "Report-Msgid-Bugs-To: %s\n"
        "POT-Creation-Date: %s\n"
        "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
        "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
        "Language-Team: LANGUAGE <LL@li.org>\n"
        "Language: \n"
        "MIME-Version: 1.0\n"
        "Content-Type: text/plain; charset=CHARSET\n"
        "Content-Transfer-Encoding: 8bit\n"

`, opts.PackageName, opts.MsgIDBugsAddress, formatTime())
	fmt.Fprintf(out, "%s", header)

	// yes, this is the way to do it in go
	sortedKeys := []string{}
	for k := range msgIDs {
		sortedKeys = append(sortedKeys, k)
	}
	if opts.SortOutput {
		sort.Strings(sortedKeys)
	}

	// FIXME: use template here?
	for _, k := range sortedKeys {
		msgidList := msgIDs[k]
		for _, msgid := range msgidList {
			if opts.AddComments || opts.AddCommentsTag != "" {
				fmt.Fprintf(out, "%s", msgid.comment)
			}
		}
		if !opts.NoLocation {
			fmt.Fprintf(out, "#:")
			for _, msgid := range msgidList {
				fmt.Fprintf(out, " %s:%d", msgid.fname, msgid.line)
			}
			fmt.Fprintf(out, "\n")
		}
		msgid := msgidList[0]
		if msgid.formatHint != "" {
			fmt.Fprintf(out, "#, %s\n", msgid.formatHint)
		}
		var formatOutput = func(in string) string {
			// split string with \n into multiple lines
			// to make the output nicer
			out := strings.Replace(in, "\\n", "\\n\"\n        \"", -1)
			// cleanup too aggressive splitting (empty "" lines)
			return strings.TrimSuffix(out, "\"\n        \"")
		}
		fmt.Fprintf(out, "msgid   \"%v\"\n", formatOutput(k))
		if msgid.msgidPlural != "" {
			fmt.Fprintf(out, "msgid_plural   \"%v\"\n", formatOutput(msgid.msgidPlural))
			fmt.Fprintf(out, "msgstr[0]  \"\"\n")
			fmt.Fprintf(out, "msgstr[1]  \"\"\n")
		} else {
			fmt.Fprintf(out, "msgstr  \"\"\n")
		}
		fmt.Fprintf(out, "\n")
	}

}

// FIXME: this must be setable via go-flags
var opts struct {
	Output string `short:"o" long:"output" description:"output to specified file"`

	AddComments bool `short:"c" long:"add-comments" description:"place all comment blocks preceding keyword lines in output file"`

	AddCommentsTag string `long:"add-comments-tag" description:"place comment blocks starting with TAG and prceding keyword lines in output file"`

	SortOutput bool `short:"s" long:"sort-output" description:"generate sorted output"`

	NoLocation bool `long:"no-location" description:"do not write '#: filename:line' lines"`

	MsgIDBugsAddress string `long:"msgid-bugs-address" default:"EMAIL" description:"set report address for msgid bugs"`

	PackageName string `long:"package-name" description:"set package name in output"`

	Keyword       string `short:"k" long:"keyword" default:"gettext.Gettext" description:"look for WORD as the keyword for singular strings"`
	KeywordPlural string `long:"keyword-plural" default:"gettext.NGettext" description:"look for WORD as the keyword for plural strings"`
}

func main() {
	// parse args
	args, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		log.Fatalf("ParseArgs failed %s", err)
	}

	if err := processFiles(args[1:]); err != nil {
		log.Fatalf("processFiles failed with: %s", err)
	}

	out := os.Stdout
	if opts.Output != "" {
		var err error
		out, err = os.Create(opts.Output)
		if err != nil {
			log.Fatalf("failed to create %s: %s", opts.Output, err)
		}
	}
	writePotFile(out)
}
<commit_msg>Closes #7<commit_after>// -*- Mode: Go; indent-tabs-mode: t -*-

/*
 * Copyright (C) 2015-2016 Canonical Ltd
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io"
	"io/ioutil"
	"log"
	"os"
	"sort"
	"strings"
	"time"

	"github.com/jessevdk/go-flags"
)

type msgID struct {
	msgidPlural string
	comment     string
	fname       string
	line        int
	formatHint  string
}

var msgIDs map[string][]msgID

func formatComment(com string) string {
	out := ""
	for _, rawline := range strings.Split(com, "\n") {
		line := rawline
		line = strings.TrimPrefix(line, "//")
		line = strings.TrimPrefix(line, "/*")
		line = strings.TrimSuffix(line, "*/")
		line = strings.TrimSpace(line)
		if line != "" {
			out += fmt.Sprintf("#. %s\n", line)
		}
	}

	return out
}

func findCommentsForTranslation(fset *token.FileSet, f *ast.File, posCall token.Position) string {
	com := ""
	for _, cg := range f.Comments {
		// search for all comments in the previous line
		for i := len(cg.List) - 1; i >= 0; i-- {
			c := cg.List[i]

			posComment := fset.Position(c.End())
			//println(posCall.Line, posComment.Line, c.Text)
			if posCall.Line == posComment.Line+1 {
				posCall = posComment
				com = fmt.Sprintf("%s\n%s", c.Text, com)
			}
		}
	}

	// only return if we have a matching prefix
	formatedComment := formatComment(com)
	needle := fmt.Sprintf("#. %s", opts.AddCommentsTag)
	if !strings.HasPrefix(formatedComment, needle) {
		formatedComment = ""
	}

	return formatedComment
}

func constructValue(val interface{}) string {
	switch val.(type) {
	case *ast.BasicLit:
		return val.(*ast.BasicLit).Value
	// this happens for constructs like:
	//  gettext.Gettext("foo" + "bar")
	case *ast.BinaryExpr:
		// we only support string concat
		if val.(*ast.BinaryExpr).Op != token.ADD {
			return ""
		}
		left := constructValue(val.(*ast.BinaryExpr).X)
		// strip right " (or `)
		left = left[0 : len(left)-1]
		right := constructValue(val.(*ast.BinaryExpr).Y)
		// strip left " (or `)
		right = right[1:len(right)]
		return left + right
	default:
		panic(fmt.Sprintf("unknown type: %v", val))
	}
}

func inspectNodeForTranslations(fset *token.FileSet, f *ast.File, n ast.Node) bool {
	// FIXME: this assume we always have a "gettext.Gettext" style keyword
	var gettextSelector, gettextFuncName string
	l := strings.Split(opts.Keyword, ".")

	if len(l) > 1 {
		gettextSelector = l[0]
		gettextFuncName = l[1]
	} else {
		gettextFuncName = l[0]
	}

	var gettextSelectorPlural, gettextFuncNamePlural string
	l = strings.Split(opts.KeywordPlural, ".")

	if len(l) > 1 {
		gettextSelectorPlural = l[0]
		gettextFuncNamePlural = l[1]
	} else {
		gettextFuncNamePlural = l[0]
	}

	switch x := n.(type) {
	case *ast.CallExpr:
		var i18nStr, i18nStrPlural string
		//if sel, ok := x.Fun.(*ast.Ident); ok {

		//}
		switch sel := x.Fun.(type) {
		case *ast.Ident:
			if sel.Name == gettextFuncNamePlural {
				i18nStr = x.Args[0].(*ast.BasicLit).Value
				i18nStrPlural = x.Args[1].(*ast.BasicLit).Value
			}
			if sel.Name == gettextFuncName {
				i18nStr = constructValue(x.Args[0])
			}
		case *ast.SelectorExpr:
			if sel.Sel.Name == gettextFuncNamePlural && sel.X.(*ast.Ident).Name == gettextSelectorPlural {
				i18nStr = x.Args[0].(*ast.BasicLit).Value
				i18nStrPlural = x.Args[1].(*ast.BasicLit).Value
			}

			if sel.Sel.Name == gettextFuncName && sel.X.(*ast.Ident).Name == gettextSelector {
				i18nStr = constructValue(x.Args[0])
			}
		}

		if i18nStr == "" {
			break
		}

		// FIXME: too simplistic(?), no %% is considered
		formatHint := ""
		if strings.Contains(i18nStr, "%") || strings.Contains(i18nStrPlural, "%") {
			// well, not quite correct but close enough
			formatHint = "c-format"
		}

		msgidStr := formatI18nStr(i18nStr)
		posCall := fset.Position(n.Pos())
		msgIDs[msgidStr] = append(msgIDs[msgidStr], msgID{
			formatHint:  formatHint,
			msgidPlural: formatI18nStr(i18nStrPlural),
			fname:       posCall.Filename,
			line:        posCall.Line,
			comment:     findCommentsForTranslation(fset, f, posCall),
		})
	}

	return true
}

func formatI18nStr(s string) string {
	if s == "" {
		return ""
	}
	// the "`" is special
	if s[0] == '`' {
		// replace inner " with \"
		s = strings.Replace(s, "\"", "\\\"", -1)
		// replace \n with \\n
		s = strings.Replace(s, "\n", "\\n", -1)
	}
	// strip leading and trailing " (or `)
	s = s[1 : len(s)-1]
	return s
}

func processFiles(args []string) error {
	// go over the input files
	msgIDs = make(map[string][]msgID)

	fset := token.NewFileSet()
	for _, fname := range args {
		if err := processSingleGoSource(fset, fname); err != nil {
			return err
		}
	}

	return nil
}

func processSingleGoSource(fset *token.FileSet, fname string) error {
	fnameContent, err := ioutil.ReadFile(fname)
	if err != nil {
		panic(err)
	}

	// Create the AST by parsing src.
	f, err := parser.ParseFile(fset, fname, fnameContent, parser.ParseComments)
	if err != nil {
		panic(err)
	}

	ast.Inspect(f, func(n ast.Node) bool {
		return inspectNodeForTranslations(fset, f, n)
	})

	return nil
}

var formatTime = func() string {
	return time.Now().Format("2006-01-02 15:04-0700")
}

func writePotFile(out io.Writer) {

	header := fmt.Sprintf(`# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid   ""
msgstr  "Project-Id-Version: %s\n"
        "Report-Msgid-Bugs-To: %s\n"
        "POT-Creation-Date: %s\n"
        "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
        "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
        "Language-Team: LANGUAGE <LL@li.org>\n"
        "Language: \n"
        "MIME-Version: 1.0\n"
        "Content-Type: text/plain; charset=CHARSET\n"
        "Content-Transfer-Encoding: 8bit\n"

`, opts.PackageName, opts.MsgIDBugsAddress, formatTime())
	fmt.Fprintf(out, "%s", header)

	// yes, this is the way to do it in go
	sortedKeys := []string{}
	for k := range msgIDs {
		sortedKeys = append(sortedKeys, k)
	}
	if opts.SortOutput {
		sort.Strings(sortedKeys)
	}

	// FIXME: use template here?
	for _, k := range sortedKeys {
		msgidList := msgIDs[k]
		for _, msgid := range msgidList {
			if opts.AddComments || opts.AddCommentsTag != "" {
				fmt.Fprintf(out, "%s", msgid.comment)
			}
		}
		if !opts.NoLocation {
			fmt.Fprintf(out, "#:")
			for _, msgid := range msgidList {
				fmt.Fprintf(out, " %s:%d", msgid.fname, msgid.line)
			}
			fmt.Fprintf(out, "\n")
		}
		msgid := msgidList[0]
		if msgid.formatHint != "" {
			fmt.Fprintf(out, "#, %s\n", msgid.formatHint)
		}
		var formatOutput = func(in string) string {
			// split string with \n into multiple lines
			// to make the output nicer
			out := strings.Replace(in, "\\n", "\\n\"\n        \"", -1)
			// cleanup too aggressive splitting (empty "" lines)
			return strings.TrimSuffix(out, "\"\n        \"")
		}
		fmt.Fprintf(out, "msgid   \"%v\"\n", formatOutput(k))
		if msgid.msgidPlural != "" {
			fmt.Fprintf(out, "msgid_plural   \"%v\"\n", formatOutput(msgid.msgidPlural))
			fmt.Fprintf(out, "msgstr[0]  \"\"\n")
			fmt.Fprintf(out, "msgstr[1]  \"\"\n")
		} else {
			fmt.Fprintf(out, "msgstr  \"\"\n")
		}
		fmt.Fprintf(out, "\n")
	}

}

// FIXME: this must be setable via go-flags
var opts struct {
	Output string `short:"o" long:"output" description:"output to specified file"`

	AddComments bool `short:"c" long:"add-comments" description:"place all comment blocks preceding keyword lines in output file"`

	AddCommentsTag string `long:"add-comments-tag" description:"place comment blocks starting with TAG and prceding keyword lines in output file"`

	SortOutput bool `short:"s" long:"sort-output" description:"generate sorted output"`

	NoLocation bool `long:"no-location" description:"do not write '#: filename:line' lines"`

	MsgIDBugsAddress string `long:"msgid-bugs-address" default:"EMAIL" description:"set report address for msgid bugs"`

	PackageName string `long:"package-name" description:"set package name in output"`

	Keyword       string `short:"k" long:"keyword" default:"gettext.Gettext" description:"look for WORD as the keyword for singular strings"`
	KeywordPlural string `long:"keyword-plural" default:"gettext.NGettext" description:"look for WORD as the keyword for plural strings"`
}

func main() {
	// parse args
	args, err := flags.ParseArgs(&opts, os.Args)
	if err != nil {
		log.Fatalf("ParseArgs failed %s", err)
	}

	if err := processFiles(args[1:]); err != nil {
		log.Fatalf("processFiles failed with: %s", err)
	}

	out := os.Stdout
	if opts.Output != "" {
		var err error
		out, err = os.Create(opts.Output)
		if err != nil {
			log.Fatalf("failed to create %s: %s", opts.Output, err)
		}
	}
	writePotFile(out)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/rkoesters/xkcd"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
)

func main() {
	var info xkcd.ComicInfo
	var err error

	switch len(os.Args) {
	case 1:
		info, err = xkcd.GetCurrentComicInfo()
		if err != nil {
			log.Fatal(err)
		}
	case 2:
		num, err := strconv.Atoi(os.Args[1])
		if err != nil {
			log.Fatal(err)
		}

		info, err = xkcd.GetComicInfo(num)
		if err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatal("args")
	}

	resp, err := http.Get(info.Img)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	_, err = io.Copy(os.Stdout, resp.Body)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Updated xkcd-get.<commit_after>package main

import (
	"github.com/rkoesters/xkcd"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
)

func main() {
	var comic xkcd.Comic
	var err error

	switch len(os.Args) {
	case 1:
		comic, err = xkcd.GetCurrentComic()
		if err != nil {
			log.Fatal(err)
		}
	case 2:
		num, err := strconv.Atoi(os.Args[1])
		if err != nil {
			log.Fatal(err)
		}

		comic, err = xkcd.GetComic(num)
		if err != nil {
			log.Fatal(err)
		}
	default:
		log.Fatal("args")
	}

	resp, err := http.Get(comic.Img)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	_, err = io.Copy(os.Stdout, resp.Body)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package xml

import "testing"
import "fmt"

func TestAddChild(t *testing.T) {

	docAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedDocAfterAdd :=
			`<?xml version="1.0" encoding="utf-8"?>
<foo>
  <bar/>
</foo>
`
		doc.Root().AddChild("<bar></bar>")

		return doc.String(), expectedDocAfterAdd, "output of the xml doc after AddChild does not match"
	}

	nodeAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedNodeAfterAdd :=
			`<foo>
  <bar/>
</foo>`

		return doc.Root().String(), expectedNodeAfterAdd, "the output of the xml root after AddChild does not match"
	}

	RunTest(t, "node", "add_child", nil, docAssertion, nodeAssertion)

}

func TestAddAncestorAsChild(t *testing.T) {
	docAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedDocAfterAdd :=
			`<?xml version="1.0" encoding="utf-8"?>
<foo/>
`

		foo := doc.Root()
		bar := foo.FirstChild()
		holiday := bar.FirstChild()
		fun := holiday.FirstChild()
		fun.AddChild(bar)

		return doc.String(), expectedDocAfterAdd, "output of the xml doc after AddChild does not match"
	}

	nodeAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedNodeAfterAdd :=
			`<foo/>`

		return doc.Root().String(), expectedNodeAfterAdd, "the output of the xml root after AddChild does not match"
	}

	RunTest(t, "node", "add_ancestor", nil, docAssertion, nodeAssertion)

}

func addChildBenchLogic(b *testing.B, doc *XmlDocument) {
	root := doc.Root()

	for i := 0; i < b.N; i++ {
		root.AddChild("<bar></bar>")
	}
}

func BenchmarkAddChild(b *testing.B) {
	RunBenchmark(b, "document", "big_un", addChildBenchLogic) // Run against big doc
}

func BenchmarkAddChildBigDoc(b *testing.B) {
	RunBenchmark(b, "node", "add_child", addChildBenchLogic)
}

func TestAddPreviousSibling(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		err := doc.Root().AddPreviousSibling("<bar></bar><cat></cat>")

		if err != nil {
			t.Errorf("Error adding previous sibling:\n%v\n", err.Error())
		}
	}

	RunTest(t, "node", "add_previous_sibling", testLogic)
}

func TestAddPreviousSibling2(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		err := doc.Root().FirstChild().AddPreviousSibling("COOL")

		if err != nil {
			t.Errorf("Error adding previous sibling:\n%v\n", err.Error())
		}
	}

	RunTest(t, "node", "add_previous_sibling2", testLogic)
}

func TestAddNextSibling(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		doc.Root().AddNextSibling("<bar></bar><baz></baz>")
	}

	RunTest(t, "node", "add_next_sibling", testLogic)
}

func TestSetContent(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetContent("<fun></fun>")
	}

	RunTest(t, "node", "set_content", testLogic)
}

func BenchmarkSetContent(b *testing.B) {

	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {
		root := doc.Root()
		for i := 0; i < b.N; i++ {
			root.SetContent("<fun></fun>")
		}
	}

	RunBenchmark(b, "node", "set_content", benchmarkLogic)
}

func TestSetChildren(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetChildren("<fun></fun>")
	}

	RunTest(t, "node", "set_children", testLogic)
}

func BenchmarkSetChildren(b *testing.B) {
	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {
		root := doc.Root()
		for i := 0; i < b.N; i++ {
			root.SetChildren("<fun></fun>")
		}
	}

	RunBenchmark(b, "node", "set_children", benchmarkLogic)
}

func TestReplace(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.Replace("<fun></fun><cool/>")
	}

	rootAssertion := func(doc *XmlDocument) (string, string, string) {
		root := doc.Root()
		return root.String(), "<fun/>", "the output of the xml root does not match"
	}

	RunTest(t, "node", "replace", testLogic, rootAssertion)
}

func BenchmarkReplace(b *testing.B) {

	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {
		root := doc.Root()
		for i := 0; i < b.N; i++ {
			root.Replace("<fun></fun>")
			root = doc.Root() //once the node has been replaced, we need to get a new node
		}
	}

	RunBenchmark(b, "node", "replace", benchmarkLogic)
}

func TestAttributes(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {

		root := doc.Root()
		attributes := root.Attributes()

		if len(attributes) != 2 || attributes["myname"].String() != "ff" {
			fmt.Printf("%v, %q\n", attributes, attributes["myname"].String())
			t.Error("root's attributes do not match")
		}

		child := root.FirstChild()
		childAttributes := child.Attributes()

		if len(childAttributes) != 1 || childAttributes["class"].String() != "shine" {
			t.Error("child's attributes do not match")
		}
	}

	RunTest(t, "node", "attributes", testLogic)

}

func BenchmarkAttributes(b *testing.B) {
	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {

		root := doc.Root()

		for i := 0; i < b.N; i++ {
			root.SetAttr("garfield", "spaghetti")
		}
	}

	RunBenchmark(b, "node", "attributes", benchmarkLogic)
}

func TestInner(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetInnerHtml("<bar></bar><baz></baz>")
	}

	RunTest(t, "node", "inner", testLogic)
}
func TestInnerWithAttributes(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetInnerHtml("<bar give='me' something='good' to='eat'></bar>")
	}

	RunTest(t, "node", "inner_with_attributes", testLogic)
}

func TestSetNamespace(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetNamespace("foo", "bar")
	}

	RunTest(t, "node", "set_namespace", testLogic)
}

func TestSetDefaultNamespace(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetNamespace("", "bar")
	}

	RunTest(t, "node", "set_default_namespace", testLogic)
}

func TestDeclareNamespace(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.DeclareNamespace("foo", "bar")
		child := root.FirstChild()
		child.SetNamespace("foo", "bar")
	}

	RunTest(t, "node", "declare_namespace", testLogic)
}

func TestNamespaceAttribute(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.DeclareNamespace("foo", "bar")
		root.SetNsAttr("bar", "hello", "world")
	}

	RunTest(t, "node", "set_ns_attr", testLogic)
}

func TestUnformattedXml(t *testing.T) {
	xml := "<?xml version=\"1.0\"?>\n<foo>\n\t<bar>Test</bar>\n</foo>"
	expected := "<foo>\n\t<bar>Test</bar>\n</foo>"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
	out := root.ToUnformattedXml()
	if out != expected {
		t.Errorf("TestUnformattedXml Expected: %v\nActual: %v", expected, out)
	}

}

func TestSerializewithFomat(t *testing.T) {
	xml := "<?xml version=\"1.0\"?>\n<foo>\n\t<bar>Test</bar>\n</foo>"
	expected := "<foo>\n\t<bar>Test</bar>\n</foo>"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
	b, size := root.SerializeWithFormat(XML_SAVE_AS_XML|XML_SAVE_NO_DECL, nil, nil)
	if b == nil {
		t.Errorf("SerializeWithFormat Expected: %v\nActual: (nil)", expected)
		return
	}
	out := string(b[:size])
	if out != expected {
		t.Errorf("SerializeWithFormat Expected: %v\nActual: %v", expected, out)
	}

}

func TestEvalVariableExpr(t *testing.T) {
	xml := "<foo />"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
    s := newSimpleVariableScope()
	root := doc.Root()
    s.variables["spec"] = "XSLT 1.0"
    s.variables["number"] = 7
    v, err := root.EvalXPath("$spec", s)
    if err != nil {
        t.Errorf("%v", err)
    }
    out := v.(string)
    if out != "XSLT 1.0" {
		t.Errorf("TestEvalVariableExpr Expected: %v\nActual: %v", "XSLT 1.0", out)
    }
}

func TestEvalStringExpr(t *testing.T) {
	xml := "<foo />"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
    v, err := root.EvalXPath("\"Hello\"", nil)
    if err != nil {
        t.Errorf("%v", err)
    }
    out := v.(string)
    if out != "Hello" {
		t.Errorf("TestEvalStringExpr Expected: %v\nActual: %v", "Hello", out)
    }
}

func TestEvalNumericExpr(t *testing.T) {
	xml := "<foo />"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
    v, err := root.EvalXPath("7", nil)
    if err != nil {
        t.Errorf("%v", err)
    }
    out := v.(float64)
    if out != 7 {
		t.Errorf("TestEvalNumericExpr Expected: %v\nActual: %v", 7, out)
    }
}
<commit_msg>Run go fmt<commit_after>package xml

import "testing"
import "fmt"

func TestAddChild(t *testing.T) {

	docAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedDocAfterAdd :=
			`<?xml version="1.0" encoding="utf-8"?>
<foo>
  <bar/>
</foo>
`
		doc.Root().AddChild("<bar></bar>")

		return doc.String(), expectedDocAfterAdd, "output of the xml doc after AddChild does not match"
	}

	nodeAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedNodeAfterAdd :=
			`<foo>
  <bar/>
</foo>`

		return doc.Root().String(), expectedNodeAfterAdd, "the output of the xml root after AddChild does not match"
	}

	RunTest(t, "node", "add_child", nil, docAssertion, nodeAssertion)

}

func TestAddAncestorAsChild(t *testing.T) {
	docAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedDocAfterAdd :=
			`<?xml version="1.0" encoding="utf-8"?>
<foo/>
`

		foo := doc.Root()
		bar := foo.FirstChild()
		holiday := bar.FirstChild()
		fun := holiday.FirstChild()
		fun.AddChild(bar)

		return doc.String(), expectedDocAfterAdd, "output of the xml doc after AddChild does not match"
	}

	nodeAssertion := func(doc *XmlDocument) (string, string, string) {
		expectedNodeAfterAdd :=
			`<foo/>`

		return doc.Root().String(), expectedNodeAfterAdd, "the output of the xml root after AddChild does not match"
	}

	RunTest(t, "node", "add_ancestor", nil, docAssertion, nodeAssertion)

}

func addChildBenchLogic(b *testing.B, doc *XmlDocument) {
	root := doc.Root()

	for i := 0; i < b.N; i++ {
		root.AddChild("<bar></bar>")
	}
}

func BenchmarkAddChild(b *testing.B) {
	RunBenchmark(b, "document", "big_un", addChildBenchLogic) // Run against big doc
}

func BenchmarkAddChildBigDoc(b *testing.B) {
	RunBenchmark(b, "node", "add_child", addChildBenchLogic)
}

func TestAddPreviousSibling(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		err := doc.Root().AddPreviousSibling("<bar></bar><cat></cat>")

		if err != nil {
			t.Errorf("Error adding previous sibling:\n%v\n", err.Error())
		}
	}

	RunTest(t, "node", "add_previous_sibling", testLogic)
}

func TestAddPreviousSibling2(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		err := doc.Root().FirstChild().AddPreviousSibling("COOL")

		if err != nil {
			t.Errorf("Error adding previous sibling:\n%v\n", err.Error())
		}
	}

	RunTest(t, "node", "add_previous_sibling2", testLogic)
}

func TestAddNextSibling(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		doc.Root().AddNextSibling("<bar></bar><baz></baz>")
	}

	RunTest(t, "node", "add_next_sibling", testLogic)
}

func TestSetContent(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetContent("<fun></fun>")
	}

	RunTest(t, "node", "set_content", testLogic)
}

func BenchmarkSetContent(b *testing.B) {

	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {
		root := doc.Root()
		for i := 0; i < b.N; i++ {
			root.SetContent("<fun></fun>")
		}
	}

	RunBenchmark(b, "node", "set_content", benchmarkLogic)
}

func TestSetChildren(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetChildren("<fun></fun>")
	}

	RunTest(t, "node", "set_children", testLogic)
}

func BenchmarkSetChildren(b *testing.B) {
	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {
		root := doc.Root()
		for i := 0; i < b.N; i++ {
			root.SetChildren("<fun></fun>")
		}
	}

	RunBenchmark(b, "node", "set_children", benchmarkLogic)
}

func TestReplace(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.Replace("<fun></fun><cool/>")
	}

	rootAssertion := func(doc *XmlDocument) (string, string, string) {
		root := doc.Root()
		return root.String(), "<fun/>", "the output of the xml root does not match"
	}

	RunTest(t, "node", "replace", testLogic, rootAssertion)
}

func BenchmarkReplace(b *testing.B) {

	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {
		root := doc.Root()
		for i := 0; i < b.N; i++ {
			root.Replace("<fun></fun>")
			root = doc.Root() //once the node has been replaced, we need to get a new node
		}
	}

	RunBenchmark(b, "node", "replace", benchmarkLogic)
}

func TestAttributes(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {

		root := doc.Root()
		attributes := root.Attributes()

		if len(attributes) != 2 || attributes["myname"].String() != "ff" {
			fmt.Printf("%v, %q\n", attributes, attributes["myname"].String())
			t.Error("root's attributes do not match")
		}

		child := root.FirstChild()
		childAttributes := child.Attributes()

		if len(childAttributes) != 1 || childAttributes["class"].String() != "shine" {
			t.Error("child's attributes do not match")
		}
	}

	RunTest(t, "node", "attributes", testLogic)

}

func BenchmarkAttributes(b *testing.B) {
	benchmarkLogic := func(b *testing.B, doc *XmlDocument) {

		root := doc.Root()

		for i := 0; i < b.N; i++ {
			root.SetAttr("garfield", "spaghetti")
		}
	}

	RunBenchmark(b, "node", "attributes", benchmarkLogic)
}

func TestInner(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetInnerHtml("<bar></bar><baz></baz>")
	}

	RunTest(t, "node", "inner", testLogic)
}
func TestInnerWithAttributes(t *testing.T) {

	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetInnerHtml("<bar give='me' something='good' to='eat'></bar>")
	}

	RunTest(t, "node", "inner_with_attributes", testLogic)
}

func TestSetNamespace(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetNamespace("foo", "bar")
	}

	RunTest(t, "node", "set_namespace", testLogic)
}

func TestSetDefaultNamespace(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.SetNamespace("", "bar")
	}

	RunTest(t, "node", "set_default_namespace", testLogic)
}

func TestDeclareNamespace(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.DeclareNamespace("foo", "bar")
		child := root.FirstChild()
		child.SetNamespace("foo", "bar")
	}

	RunTest(t, "node", "declare_namespace", testLogic)
}

func TestNamespaceAttribute(t *testing.T) {
	testLogic := func(t *testing.T, doc *XmlDocument) {
		root := doc.Root()
		root.DeclareNamespace("foo", "bar")
		root.SetNsAttr("bar", "hello", "world")
	}

	RunTest(t, "node", "set_ns_attr", testLogic)
}

func TestUnformattedXml(t *testing.T) {
	xml := "<?xml version=\"1.0\"?>\n<foo>\n\t<bar>Test</bar>\n</foo>"
	expected := "<foo>\n\t<bar>Test</bar>\n</foo>"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
	out := root.ToUnformattedXml()
	if out != expected {
		t.Errorf("TestUnformattedXml Expected: %v\nActual: %v", expected, out)
	}

}

func TestSerializewithFomat(t *testing.T) {
	xml := "<?xml version=\"1.0\"?>\n<foo>\n\t<bar>Test</bar>\n</foo>"
	expected := "<foo>\n\t<bar>Test</bar>\n</foo>"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
	b, size := root.SerializeWithFormat(XML_SAVE_AS_XML|XML_SAVE_NO_DECL, nil, nil)
	if b == nil {
		t.Errorf("SerializeWithFormat Expected: %v\nActual: (nil)", expected)
		return
	}
	out := string(b[:size])
	if out != expected {
		t.Errorf("SerializeWithFormat Expected: %v\nActual: %v", expected, out)
	}

}

func TestEvalVariableExpr(t *testing.T) {
	xml := "<foo />"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	s := newSimpleVariableScope()
	root := doc.Root()
	s.variables["spec"] = "XSLT 1.0"
	s.variables["number"] = 7
	v, err := root.EvalXPath("$spec", s)
	if err != nil {
		t.Errorf("%v", err)
	}
	out := v.(string)
	if out != "XSLT 1.0" {
		t.Errorf("TestEvalVariableExpr Expected: %v\nActual: %v", "XSLT 1.0", out)
	}
}

func TestEvalStringExpr(t *testing.T) {
	xml := "<foo />"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
	v, err := root.EvalXPath("\"Hello\"", nil)
	if err != nil {
		t.Errorf("%v", err)
	}
	out := v.(string)
	if out != "Hello" {
		t.Errorf("TestEvalStringExpr Expected: %v\nActual: %v", "Hello", out)
	}
}

func TestEvalNumericExpr(t *testing.T) {
	xml := "<foo />"
	doc, _ := Parse([]byte(xml), DefaultEncodingBytes, nil, DefaultParseOption, DefaultEncodingBytes)
	root := doc.Root()
	v, err := root.EvalXPath("7", nil)
	if err != nil {
		t.Errorf("%v", err)
	}
	out := v.(float64)
	if out != 7 {
		t.Errorf("TestEvalNumericExpr Expected: %v\nActual: %v", 7, out)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"

	"time"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

var account = make(map[string]int)

var logger = shim.NewLogger("ftLogger")

// SampleChaincode struct required to implement the shim.Chaincode interface
type SampleChaincode struct {
}

// Init method is called when the chaincode is first deployed onto the blockchain network
func (t *SampleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var customerName string // Name of the customer
	var currentBalance int  // Current account balance of the customer
	var err error

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2")
	}

	// Initialize the chaincode
	customerName = args[0]
	currentBalance, err = strconv.Atoi(args[1])
	if err != nil {
		return nil, errors.New("Expecting integer value for customer account balance: " + err.Error())
	}

	logger.Info("Customer: %s, Available Balance: %d", customerName, currentBalance)

	// Save the Customer info
	account[customerName] = currentBalance

	// Write the state to the ledger
	err = stub.PutState("IBI-CC[init]: "+time.Now().String(), []byte(args[0]))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Query method is invoked whenever any read/get/query operation needs to be performed on the blockchain state.
func (t *SampleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Query is running: " + function)

	// Handle different functions
	if function == "GetAccountBalance" { //read a variable
		return t.getAccountBalance(stub, args)
	}
	logger.Error("Query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

// Invoke method is invoked whenever the state of the blockchain is to be modified.
func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Invoke is running: " + function)

	// Handle different functions
	switch function {
	case "Init":
		return t.Init(stub, "init", args)
	case "Deposit":
		return t.depositFund(stub, args)
	case "Withdraw":
		return t.withdrawFund(stub, args)
	case "Settlement":
		return t.eodSettlement(stub, args)
	default:
		logger.Error("Invoke did not find func: " + function)
	}

	return nil, errors.New("Received unknown function invocation")
}

func (t *SampleChaincode) getAccountBalance(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running getAccountBalance")
	var name string

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the var to query")
	}

	name = args[0]

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) depositFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running depositFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the customer and value to set")
	}

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for deposit amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]
	newBalance = value + currentBalance

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) withdrawFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running withdrawFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the customer and value to set")
	}

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for withdraw amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]

	if value > currentBalance {
		jsonResp = "{\"Error\":\"Insufficient Fund in account. Aborting...\"}"
		logger.Error(jsonResp)
		return nil, errors.New(jsonResp)
	}

	newBalance = currentBalance - value

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) eodSettlement(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running eodSettlement")

	var err error

	due := []byte(strconv.Itoa(0))

	// Write amount which IBI owes to ABI back to the ledger
	err = stub.PutState("IBI->ABI", due)
	if err != nil {
		logger.Error(err)
		return nil, err
	}

	return due, err
}

func main() {
	var err error
	lld, _ := shim.LogLevel("DEBUG")
	fmt.Println(lld)

	logger.SetLevel(lld)
	fmt.Println(logger.IsEnabledFor(lld))

	err = shim.Start(new(SampleChaincode))
	if err != nil {
		fmt.Println("Could not start SampleChaincode")
	} else {
		fmt.Println("SampleChaincode successfully started")
	}
}
<commit_msg>couple of log messages<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"

	"time"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

var account = make(map[string]int)

var logger = shim.NewLogger("ftLogger")

// SampleChaincode struct required to implement the shim.Chaincode interface
type SampleChaincode struct {
}

// Init method is called when the chaincode is first deployed onto the blockchain network
func (t *SampleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	var customerName string // Name of the customer
	var currentBalance int  // Current account balance of the customer
	var err error

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2")
	}

	// Initialize the chaincode
	customerName = args[0]
	currentBalance, err = strconv.Atoi(args[1])
	if err != nil {
		return nil, errors.New("Expecting integer value for customer account balance: " + err.Error())
	}

	logger.Info("Customer: %s, Available Balance: %d", customerName, currentBalance)

	// Save the Customer info
	account[customerName] = currentBalance

	// Write the state to the ledger
	err = stub.PutState("IBI-CC[init]: "+time.Now().String(), []byte(args[0]))
	if err != nil {
		return nil, err
	}

	return nil, nil
}

// Query method is invoked whenever any read/get/query operation needs to be performed on the blockchain state.
func (t *SampleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Query is running: " + function)

	// Handle different functions
	if function == "GetAccountBalance" { //read a variable
		return t.getAccountBalance(stub, args)
	}
	logger.Error("Query did not find func: " + function)

	return nil, errors.New("Received unknown function query")
}

// Invoke method is invoked whenever the state of the blockchain is to be modified.
func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	logger.Info("Invoke is running: " + function)

	// Handle different functions
	switch function {
	case "Init":
		return t.Init(stub, "init", args)
	case "Deposit":
		return t.depositFund(stub, args)
	case "Withdraw":
		return t.withdrawFund(stub, args)
	case "Settlement":
		return t.eodSettlement(stub, args)
	default:
		logger.Error("Invoke did not find func: " + function)
	}

	return nil, errors.New("Received unknown function invocation")
}

func (t *SampleChaincode) getAccountBalance(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running getAccountBalance")
	var name string

	if len(args) != 1 {
		return nil, errors.New("Incorrect number of arguments. Expecting name of the var to query")
	}

	name = args[0]

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) depositFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running depositFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the customer and value to set")
	}

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for deposit amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]
	newBalance = value + currentBalance

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) withdrawFund(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running withdrawFund")

	var name, jsonResp string
	var value, currentBalance, newBalance int
	var err error

	if len(args) != 2 {
		return nil, errors.New("Incorrect number of arguments. Expecting 2. name of the customer and value to set")
	}

	name = args[0]
	value, err = strconv.Atoi(args[1])
	if err != nil {
		jsonResp = "{\"Error\":\"Invalid input argument for withdraw amount: " + err.Error() + "\"}"
		return nil, errors.New(jsonResp)
	}

	currentBalance = account[name]

	if value > currentBalance {
		jsonResp = "{\"Error\":\"Insufficient Fund in account. Aborting...\"}"
		logger.Error(jsonResp)
		return nil, errors.New(jsonResp)
	}

	newBalance = currentBalance - value

	account[name] = newBalance

	valAsbytes := []byte(strconv.Itoa(account[name]))

	return valAsbytes, nil
}

func (t *SampleChaincode) eodSettlement(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
	logger.Info("Running eodSettlement")

	var err error

	due := []byte(strconv.Itoa(0))

	logger.Info("IBI pays back to ABI all dues, commit it in the ledger")
	err = stub.PutState("IBI->ABI", due)
	if err != nil {
		logger.Error(err)
		return nil, err
	}

	logger.Info("EOD Settlement Done!")

	return due, err
}

func main() {
	var err error
	lld, _ := shim.LogLevel("DEBUG")
	fmt.Println(lld)

	logger.SetLevel(lld)
	fmt.Println(logger.IsEnabledFor(lld))

	err = shim.Start(new(SampleChaincode))
	if err != nil {
		fmt.Println("Could not start SampleChaincode")
	} else {
		fmt.Println("SampleChaincode successfully started")
	}
}
<|endoftext|>


<commit_before>package object

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/hussar-lang/hussary/ast"
	"github.com/ttacon/chalk"
)

type ObjectType string

const (
	ERROR_OBJ        = "ERROR"
	INTEGER_OBJ      = "INTEGER"
	STRING_OBJ       = "STRING"
	BOOLEAN_OBJ      = "BOOLEAN"
	NULL_OBJ         = "NULL"
	RETURN_VALUE_OBJ = "RETURN_VALUE"
	FUNCTION_OBJ     = "FUNCTION"
	BUILTIN_OBJ      = "BUILTIN"
	ARRAY_OBJ        = "ARRAY"
	EXIT_OBJ         = "EXIT"
)

type Object interface {
	Type() ObjectType
	Inspect() string
}

// === Errors ===
type Error struct {
	Severity string
	Message  string
}

func (e *Error) Type() ObjectType { return ERROR_OBJ }
func (e *Error) Inspect() string {
	errColor := chalk.Red.NewStyle().WithTextStyle(chalk.Bold).Style
	warnColor := chalk.Yellow.NewStyle().WithTextStyle(chalk.Bold).Style

	switch e.Severity {
	case "warn":
		return warnColor("[WARN]  ") + e.Message
	default:
		return errColor("[ERROR] ") + e.Message
	}
}

// === Integer ===
type Integer struct {
	Value int64
}

func (i *Integer) Type() ObjectType { return INTEGER_OBJ }
func (i *Integer) Inspect() string  { return fmt.Sprintf("%d", i.Value) }

// === String ===
type String struct {
	Value string
}

func (s *String) Type() ObjectType { return STRING_OBJ }
func (s *String) Inspect() string  { return s.Value }

// === Boolean ===
type Boolean struct {
	Value bool
}

func (b *Boolean) Type() ObjectType { return BOOLEAN_OBJ }
func (b *Boolean) Inspect() string  { return fmt.Sprintf("%t", b.Value) }

// === Null ===
type Null struct{}

func (n *Null) Type() ObjectType { return NULL_OBJ }
func (n *Null) Inspect() string  { return "null" }

// === Return ===
type ReturnValue struct {
	Value Object
}

func (rv *ReturnValue) Type() ObjectType { return RETURN_VALUE_OBJ }
func (rv *ReturnValue) Inspect() string  { return rv.Value.Inspect() }

// === Function ===
type Function struct {
	//Name string		TODO: to be used to not have to bind to a variable explicitly
	Parameters []*ast.Identifier
	Body       *ast.BlockStatement
	Env        *Environment
}

func (f *Function) Type() ObjectType { return FUNCTION_OBJ }
func (f *Function) Inspect() string {
	var out bytes.Buffer

	params := []string{}
	for _, p := range f.Parameters {
		params = append(params, p.String())
	}

	out.WriteString("fn")
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(") {\n")
	out.WriteString(f.Body.String())
	out.WriteString("\n}")

	return out.String()
}

// === Builtin ===
type BuiltinFunction func(args ...Object) Object

type Builtin struct {
	Fn BuiltinFunction
}

func (b *Builtin) Type() ObjectType { return BUILTIN_OBJ }
func (b *Builtin) Inspect() string  { return "builtin function" }

// === Array ===
type Array struct {
	Elements []Object
}

func (a *Array) Type() ObjectType { return ARRAY_OBJ }
func (a *Array) Inspect() string {
	var out bytes.Buffer

	elements := []string{}
	for _, e := range a.Elements {
		elements = append(elements, e.Inspect())
	}

	out.WriteString("[")
	out.WriteString(strings.Join(elements, ", "))
	out.WriteString("]")

	return out.String()
}

// === Exit ===
type Exit struct {
	ExitCode *ast.Expression
}

func (e *Exit) Type() ObjectType { return EXIT_OBJ }
func (e *Exit) Inspect() string {
	var out bytes.Buffer

	out.WriteString("exit()")

	return out.String()
}
<commit_msg>fix: Fix a typo in the imports<commit_after>package object

import (
	"bytes"
	"fmt"
	"strings"

	"github.com/hussar-lang/hussar/ast"
	"github.com/ttacon/chalk"
)

type ObjectType string

const (
	ERROR_OBJ        = "ERROR"
	INTEGER_OBJ      = "INTEGER"
	STRING_OBJ       = "STRING"
	BOOLEAN_OBJ      = "BOOLEAN"
	NULL_OBJ         = "NULL"
	RETURN_VALUE_OBJ = "RETURN_VALUE"
	FUNCTION_OBJ     = "FUNCTION"
	BUILTIN_OBJ      = "BUILTIN"
	ARRAY_OBJ        = "ARRAY"
	EXIT_OBJ         = "EXIT"
)

type Object interface {
	Type() ObjectType
	Inspect() string
}

// === Errors ===
type Error struct {
	Severity string
	Message  string
}

func (e *Error) Type() ObjectType { return ERROR_OBJ }
func (e *Error) Inspect() string {
	errColor := chalk.Red.NewStyle().WithTextStyle(chalk.Bold).Style
	warnColor := chalk.Yellow.NewStyle().WithTextStyle(chalk.Bold).Style

	switch e.Severity {
	case "warn":
		return warnColor("[WARN]  ") + e.Message
	default:
		return errColor("[ERROR] ") + e.Message
	}
}

// === Integer ===
type Integer struct {
	Value int64
}

func (i *Integer) Type() ObjectType { return INTEGER_OBJ }
func (i *Integer) Inspect() string  { return fmt.Sprintf("%d", i.Value) }

// === String ===
type String struct {
	Value string
}

func (s *String) Type() ObjectType { return STRING_OBJ }
func (s *String) Inspect() string  { return s.Value }

// === Boolean ===
type Boolean struct {
	Value bool
}

func (b *Boolean) Type() ObjectType { return BOOLEAN_OBJ }
func (b *Boolean) Inspect() string  { return fmt.Sprintf("%t", b.Value) }

// === Null ===
type Null struct{}

func (n *Null) Type() ObjectType { return NULL_OBJ }
func (n *Null) Inspect() string  { return "null" }

// === Return ===
type ReturnValue struct {
	Value Object
}

func (rv *ReturnValue) Type() ObjectType { return RETURN_VALUE_OBJ }
func (rv *ReturnValue) Inspect() string  { return rv.Value.Inspect() }

// === Function ===
type Function struct {
	//Name string		TODO: to be used to not have to bind to a variable explicitly
	Parameters []*ast.Identifier
	Body       *ast.BlockStatement
	Env        *Environment
}

func (f *Function) Type() ObjectType { return FUNCTION_OBJ }
func (f *Function) Inspect() string {
	var out bytes.Buffer

	params := []string{}
	for _, p := range f.Parameters {
		params = append(params, p.String())
	}

	out.WriteString("fn")
	out.WriteString("(")
	out.WriteString(strings.Join(params, ", "))
	out.WriteString(") {\n")
	out.WriteString(f.Body.String())
	out.WriteString("\n}")

	return out.String()
}

// === Builtin ===
type BuiltinFunction func(args ...Object) Object

type Builtin struct {
	Fn BuiltinFunction
}

func (b *Builtin) Type() ObjectType { return BUILTIN_OBJ }
func (b *Builtin) Inspect() string  { return "builtin function" }

// === Array ===
type Array struct {
	Elements []Object
}

func (a *Array) Type() ObjectType { return ARRAY_OBJ }
func (a *Array) Inspect() string {
	var out bytes.Buffer

	elements := []string{}
	for _, e := range a.Elements {
		elements = append(elements, e.Inspect())
	}

	out.WriteString("[")
	out.WriteString(strings.Join(elements, ", "))
	out.WriteString("]")

	return out.String()
}

// === Exit ===
type Exit struct {
	ExitCode *ast.Expression
}

func (e *Exit) Type() ObjectType { return EXIT_OBJ }
func (e *Exit) Inspect() string {
	var out bytes.Buffer

	out.WriteString("exit()")

	return out.String()
}
<|endoftext|>


<commit_before>package client

import (
	"context"
	"github.com/imdario/mergo"
	"github.com/ory/fosite"
	"github.com/pborman/uuid"
	"github.com/pkg/errors"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// MongoManager cares for the managing of the Mongo Session instance of a Client
type MongoManager struct {
	DB     *mgo.Database
	Hasher fosite.Hasher
}

// GetClient returns a Client if found by an ID lookup.
func (m *MongoManager) GetClient(ctx context.Context, id string) (fosite.Client, error) {
	return m.GetConcreteClient(id)
}

// UpdateClient updates an OAuth 2.0 Client record. This is done using the equivalent of an object replace.
func (m *MongoManager) UpdateClient(c *Client) error {
	o, err := m.GetConcreteClient(c.ID)
	if err != nil {
		return errors.WithStack(err)
	}

	// If the password isn't updated, grab it from the stored object
	if c.Secret == "" {
		c.Secret = string(c.GetHashedSecret())
	} else {
		h, err := m.Hasher.Hash([]byte(c.Secret))
		if err != nil {
			return errors.WithStack(err)
		}
		c.Secret = string(h)
	}

	// Otherwise, update the object with the new updates
	if err := mergo.Merge(c, o); err != nil {
		return errors.WithStack(err)
	}

	// Update Mongo reference with the updated object
	collection := m.DB.C("clients").With(m.DB.Session.Copy())
	defer collection.Database.Session.Close()
	selector := bson.M{"_id": c.ID}
	if err := collection.Update(selector, c); err != nil {
		return errors.WithStack(err)
	}
	return nil
}

// GetConcreteClient finds a Client based on ID and returns it, if found in Mongo.
func (m *MongoManager) GetConcreteClient(id string) (*Client, error) {
	collection := m.DB.C("clients").With(m.DB.Session.Copy())
	defer collection.Database.Session.Close()

	client := &Client{}
	err := collection.Find(bson.M{"_id": id}).One(client)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return client, nil
}

// Authenticate compares a client secret with the client's stored hashed secret
func (m *MongoManager) Authenticate(id string, secret []byte) (*Client, error) {
	c, err := m.GetConcreteClient(id)
	if err != nil {
		return nil, errors.WithStack(err)
	}

	if err := m.Hasher.Compare(c.GetHashedSecret(), secret); err != nil {
		return nil, errors.WithStack(err)
	}
	return c, nil
}

// CreateClient adds a new OAuth2.0 Client to the client store.
func (m *MongoManager) CreateClient(c *Client) error {
	if c.ID == "" {
		c.ID = uuid.New()
	}

	// Hash incoming secret
	h, err := m.Hasher.Hash([]byte(c.Secret))
	if err != nil {
		return errors.WithStack(err)
	}
	c.Secret = string(h)

	// Insert to Mongo
	collection := m.DB.C("clients").With(m.DB.Session.Copy())
	defer collection.Database.Session.Close()
	if err := collection.Insert(c); err != nil {
		return errors.WithStack(err)
	}
	return nil
}
<commit_msg>:arrow_up: Client: Add DeleteClient method<commit_after>package client

import (
	"context"
	"github.com/imdario/mergo"
	"github.com/ory/fosite"
	"github.com/pborman/uuid"
	"github.com/pkg/errors"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

// MongoManager cares for the managing of the Mongo Session instance of a Client
type MongoManager struct {
	DB     *mgo.Database
	Hasher fosite.Hasher
}

// GetClient returns a Client if found by an ID lookup.
func (m *MongoManager) GetClient(ctx context.Context, id string) (fosite.Client, error) {
	return m.GetConcreteClient(id)
}

// UpdateClient updates an OAuth 2.0 Client record. This is done using the equivalent of an object replace.
func (m *MongoManager) UpdateClient(c *Client) error {
	o, err := m.GetConcreteClient(c.ID)
	if err != nil {
		return errors.WithStack(err)
	}

	// If the password isn't updated, grab it from the stored object
	if c.Secret == "" {
		c.Secret = string(c.GetHashedSecret())
	} else {
		h, err := m.Hasher.Hash([]byte(c.Secret))
		if err != nil {
			return errors.WithStack(err)
		}
		c.Secret = string(h)
	}

	// Otherwise, update the object with the new updates
	if err := mergo.Merge(c, o); err != nil {
		return errors.WithStack(err)
	}

	// Update Mongo reference with the updated object
	collection := m.DB.C("clients").With(m.DB.Session.Copy())
	defer collection.Database.Session.Close()
	selector := bson.M{"_id": c.ID}
	if err := collection.Update(selector, c); err != nil {
		return errors.WithStack(err)
	}
	return nil
}

// GetConcreteClient finds a Client based on ID and returns it, if found in Mongo.
func (m *MongoManager) GetConcreteClient(id string) (*Client, error) {
	collection := m.DB.C("clients").With(m.DB.Session.Copy())
	defer collection.Database.Session.Close()

	client := &Client{}
	err := collection.Find(bson.M{"_id": id}).One(client)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return client, nil
}

// Authenticate compares a client secret with the client's stored hashed secret
func (m *MongoManager) Authenticate(id string, secret []byte) (*Client, error) {
	c, err := m.GetConcreteClient(id)
	if err != nil {
		return nil, errors.WithStack(err)
	}

	if err := m.Hasher.Compare(c.GetHashedSecret(), secret); err != nil {
		return nil, errors.WithStack(err)
	}
	return c, nil
}

// CreateClient adds a new OAuth2.0 Client to the client store.
func (m *MongoManager) CreateClient(c *Client) error {
	if c.ID == "" {
		c.ID = uuid.New()
	}

	// Hash incoming secret
	h, err := m.Hasher.Hash([]byte(c.Secret))
	if err != nil {
		return errors.WithStack(err)
	}
	c.Secret = string(h)

	// Insert to Mongo
	collection := m.DB.C("clients").With(m.DB.Session.Copy())
	defer collection.Database.Session.Close()
	if err := collection.Insert(c); err != nil {
		return errors.WithStack(err)
	}
	return nil
}

// DeleteClient removes an OAuth 2.0 Client from the client store
func (m *MongoManager) DeleteClient(id string) error {
	collection := m.DB.C("clients").With(m.DB.Session.Copy())
	defer collection.Database.Session.Close()
	if err := collection.Remove(bson.M{"_id": id}); err != nil {
		return errors.WithStack(err)
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"time"
)

const (
	resultsDir = "results"

	modelFilename    = "model.zpl"
	solutionFilename = "scip.sol"
	outputFilename   = "output.log"

	timeLimitSec  = 3 * 60
	memoryLimitMB = 100
)

func runSolver(dir string) {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		return
	}

	// TODO: add limit on number of parallel solver runs

	commands := fmt.Sprintf("set limits time %d "+
		"set limits memory %d "+
		"read %s  opt  write solution %s  quit",
		timeLimitSec, memoryLimitMB,
		modelFilename, solutionFilename)
	cmd := exec.Command("scip", "-c", commands, "-l", outputFilename)
	cmd.Dir = dir
	_ = cmd.Run()
}

func solve(dir string) (err error) {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		return err
	}

	// for now, just start new process for every call
	go runSolver(dir)

	return nil
}

func inputHandler(w http.ResponseWriter, r *http.Request) {
	err := inputTemplate.Execute(w, nil)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func solveHandler(w http.ResponseWriter, r *http.Request) {
	model := r.FormValue("model")
	hash := fmt.Sprintf("%x", sha1.Sum([]byte(model)))

	dir := path.Join(resultsDir, hash)
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err = os.MkdirAll(dir, 0755)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		filename := path.Join(dir, modelFilename)
		err = ioutil.WriteFile(filename, []byte(model), 0644)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		err = solve(dir)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}

	// add short sleep so that result might already exist when we
	// finally redirect.
	time.Sleep(100 * time.Millisecond)

	http.Redirect(w, r, "/result/"+hash, http.StatusFound)
}

type Result struct {
	Hash     string
	Model    string
	Solution string
	Output   string
}

func resultHandler(w http.ResponseWriter, r *http.Request) {
	hash := r.URL.Path[len("/result/"):]

	dir := path.Join(resultsDir, hash)
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	res := &Result{Hash: hash, Model: "", Solution: "", Output: ""}

	model := path.Join(dir, modelFilename)
	if _, err := os.Stat(model); err == nil {
		content, err := ioutil.ReadFile(model)
		if err == nil {
			res.Model = string(content)
		}
	}

	sol := path.Join(dir, solutionFilename)
	if _, err := os.Stat(sol); err == nil {
		content, err := ioutil.ReadFile(sol)
		if err == nil {
			res.Solution = string(content)
		}
	}

	out := path.Join(dir, outputFilename)
	if _, err := os.Stat(out); err == nil {
		content, err := ioutil.ReadFile(out)
		if err == nil {
			res.Output = string(content)
		}
	}

	if err := resultTemplate.Execute(w, res); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	http.HandleFunc("/", inputHandler)
	http.HandleFunc("/solve/", solveHandler)
	http.HandleFunc("/result/", resultHandler)
	log.Fatal(http.ListenAndServe(":8080", nil))
}
<commit_msg>add command-line flags<commit_after>package main

import (
	"crypto/sha1"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"time"
)

const (
	resultsDir = "results"

	modelFilename    = "model.zpl"
	solutionFilename = "scip.sol"
	outputFilename   = "output.log"
)

var (
	timeLimitSec  = flag.Int("time", 3*60, "SCIP time limit (s)")
	memoryLimitMB = flag.Int("mem", 100, "SCIP memory limit (MB)")
	sleepTime     = flag.Int("sleep", 100, "sleep before redirect to results (ms)")
	address       = flag.String("address", ":8080", "hostname:port of server")
)

func runSolver(dir string) {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		return
	}

	// TODO: add limit on number of parallel solver runs

	commands := fmt.Sprintf("set limits time %d "+
		"set limits memory %d "+
		"read %s  opt  write solution %s  quit",
		*timeLimitSec, *memoryLimitMB,
		modelFilename, solutionFilename)
	cmd := exec.Command("scip", "-c", commands, "-l", outputFilename)
	cmd.Dir = dir
	_ = cmd.Run()
}

func solve(dir string) (err error) {
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		return err
	}

	// for now, just start new process for every call
	go runSolver(dir)

	return nil
}

func inputHandler(w http.ResponseWriter, r *http.Request) {
	err := inputTemplate.Execute(w, nil)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}

func solveHandler(w http.ResponseWriter, r *http.Request) {
	model := r.FormValue("model")
	hash := fmt.Sprintf("%x", sha1.Sum([]byte(model)))

	dir := path.Join(resultsDir, hash)
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		err = os.MkdirAll(dir, 0755)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		filename := path.Join(dir, modelFilename)
		err = ioutil.WriteFile(filename, []byte(model), 0644)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		err = solve(dir)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}

	// add short sleep so that result might already exist when we
	// finally redirect.
	time.Sleep(time.Duration(*sleepTime) * time.Millisecond)

	http.Redirect(w, r, "/result/"+hash, http.StatusFound)
}

type Result struct {
	Hash     string
	Model    string
	Solution string
	Output   string
}

func resultHandler(w http.ResponseWriter, r *http.Request) {
	hash := r.URL.Path[len("/result/"):]

	dir := path.Join(resultsDir, hash)
	if _, err := os.Stat(dir); os.IsNotExist(err) {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	res := &Result{Hash: hash, Model: "", Solution: "", Output: ""}

	model := path.Join(dir, modelFilename)
	if _, err := os.Stat(model); err == nil {
		content, err := ioutil.ReadFile(model)
		if err == nil {
			res.Model = string(content)
		}
	}

	sol := path.Join(dir, solutionFilename)
	if _, err := os.Stat(sol); err == nil {
		content, err := ioutil.ReadFile(sol)
		if err == nil {
			res.Solution = string(content)
		}
	}

	out := path.Join(dir, outputFilename)
	if _, err := os.Stat(out); err == nil {
		content, err := ioutil.ReadFile(out)
		if err == nil {
			res.Output = string(content)
		}
	}

	if err := resultTemplate.Execute(w, res); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	flag.Parse()

	http.HandleFunc("/", inputHandler)
	http.HandleFunc("/solve/", solveHandler)
	http.HandleFunc("/result/", resultHandler)
	log.Fatal(http.ListenAndServe(*address, nil))
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
)

const (
	cidr      = "0.0.0.0/0"
	beginPort = 80
	endPort   = 65535

	arinAPIEndpoint = "http://whois.arin.net/rest/ip/%s"
)

func main() {
	// On ^C, or SIGTERM handle exit.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		for sig := range c {
			logrus.Infof("Received %s, exiting.", sig.String())
			os.Exit(0)
		}
	}()

	// Set the logger to nil so we ignore messages from the Dial that don't matter.
	// See: https://github.com/golang/go/issues/19895#issuecomment-292793756
	log.SetFlags(0)
	log.SetOutput(ioutil.Discard)

	logrus.Infof("Scanning for Kubernetes Dashboards and API Servers on %s over port range %d-%d", cidr, beginPort, endPort)
	logrus.Infof("This may take a bit...")

	startTime := time.Now()

	ip, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		logrus.Fatal(err)
	}

	var wg sync.WaitGroup
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		wg.Add(1)
		go func(ip string) {
			defer wg.Done()

			for port := beginPort; port <= endPort; port++ {
				// Check if the port is open.
				ok := portOpen(ip, port)
				if !ok {
					return
				}

				// Check if it's a kubernetes dashboard.
				ok = isKubernetesDashboard(ip, port)
				if !ok {
					return
				}

				fmt.Printf("%s:%d\n", ip, port)
				// Get the info for the ip address.
				info, err := getIPInfo(ip)
				if err != nil {
					logrus.Warnf("ip info err: %v", err)
					return
				}
				fmt.Printf("%s:%d\t%s\t%s\t%s\n",
					ip, port,
					info.Net.Organization.Handle, info.Net.Organization.Name, info.Net.Organization.Reference)
			}
		}(ip.String())
	}

	wg.Wait()

	since := time.Since(startTime)
	logrus.Infof("Scan took: %s", since.String())
}

func portOpen(ip string, port int) bool {
	c, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), 2*time.Second)
	if err != nil {
		// logrus.Warnf("listen at %s:%s failed: %v", ip, port, err)
		return false
	}
	defer c.Close()

	return true
}

func isKubernetesDashboard(ip string, port int) bool {
	client := &http.Client{
		Timeout: time.Second * 3,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	tryAddrs := []string{
		fmt.Sprintf("http://%s:%d", ip, port),
		fmt.Sprintf("https://%s:%d", ip, port),
		fmt.Sprintf("http://%s:%d/api/", ip, port),
		fmt.Sprintf("https://%s:%d/api/", ip, port),
	}

	var (
		resp *http.Response
		err  = errors.New("not yet run")
		uri  string
	)

	for i := 0; i < len(tryAddrs) && err != nil; i++ {
		uri = tryAddrs[i]
		resp, err = client.Get(uri)
	}
	if err != nil {
		//logrus.Warnf("getting %s:%s failed: %v", ip, port, err)
		return false
	}
	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return false
	}

	body := strings.ToLower(string(b))
	if (strings.Contains(body, "kubernetes") && strings.Contains(body, "pod")) ||
		(strings.Contains(body, "versions") && strings.Contains(body, "serverAddress")) {
		logrus.Infof("uri: %s", uri)
		return true
	}

	return false
}

type ARINResponse struct {
	Net NetJSON `json:"net,omitempty"`
}

type NetJSON struct {
	Organization OrganizationJSON `json:"orgRef,omitempty"`
}

type OrganizationJSON struct {
	Handle    string `json:"@handle,omitempty"`
	Name      string `json:"@name,omitempty"`
	Reference string `json:"$,omitempty"`
}

func getIPInfo(ip string) (b ARINResponse, err error) {
	req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(arinAPIEndpoint, ip), nil)
	if err != nil {
		return b, err
	}
	req.Header.Set("Accept", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return b, err
	}
	defer resp.Body.Close()

	if err := json.NewDecoder(resp.Body).Decode(&b); err != nil {
		return b, err
	}

	return b, nil
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}
<commit_msg>cleanup<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/signal"
	"strings"
	"sync"
	"syscall"
	"time"

	"github.com/Sirupsen/logrus"
)

const (
	cidr      = "0.0.0.0/0"
	beginPort = 80
	endPort   = 65535

	arinAPIEndpoint = "http://whois.arin.net/rest/ip/%s"
)

func main() {
	// On ^C, or SIGTERM handle exit.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		for sig := range c {
			logrus.Infof("Received %s, exiting.", sig.String())
			os.Exit(0)
		}
	}()

	// Set the logger to nil so we ignore messages from the Dial that don't matter.
	// See: https://github.com/golang/go/issues/19895#issuecomment-292793756
	log.SetFlags(0)
	log.SetOutput(ioutil.Discard)

	logrus.Infof("Scanning for Kubernetes Dashboards and API Servers on %s over port range %d-%d", cidr, beginPort, endPort)
	logrus.Infof("This may take a bit...")

	startTime := time.Now()

	ip, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		logrus.Fatal(err)
	}

	var wg sync.WaitGroup
	for ip := ip.Mask(ipnet.Mask); ipnet.Contains(ip); inc(ip) {
		wg.Add(1)
		go func(ip string) {
			defer wg.Done()

			scanIP(ip)
		}(ip.String())
	}

	wg.Wait()

	since := time.Since(startTime)
	logrus.Infof("Scan took: %s", since.String())
}

func scanIP(ip string) {
	for port := beginPort; port <= endPort; port++ {
		// Check if the port is open.
		ok := portOpen(ip, port)
		if !ok {
			return
		}

		// Check if it's a kubernetes dashboard.
		ok = isKubernetesDashboard(ip, port)
		if !ok {
			return
		}

		fmt.Printf("%s:%d\n", ip, port)
		// Get the info for the ip address.
		info, err := getIPInfo(ip)
		if err != nil {
			logrus.Warnf("ip info err: %v", err)
			return
		}
		fmt.Printf("%s:%d\t%s\t%s\t%s\n",
			ip, port,
			info.Net.Organization.Handle, info.Net.Organization.Name, info.Net.Organization.Reference)
	}
}

func portOpen(ip string, port int) bool {
	c, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), 2*time.Second)
	if err != nil {
		// logrus.Warnf("listen at %s:%s failed: %v", ip, port, err)
		return false
	}
	defer c.Close()

	return true
}

func isKubernetesDashboard(ip string, port int) bool {
	client := &http.Client{
		Timeout: time.Second * 3,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	tryAddrs := []string{
		fmt.Sprintf("http://%s:%d", ip, port),
		fmt.Sprintf("https://%s:%d", ip, port),
		fmt.Sprintf("http://%s:%d/api/", ip, port),
		fmt.Sprintf("https://%s:%d/api/", ip, port),
	}

	var (
		resp *http.Response
		err  = errors.New("not yet run")
		uri  string
	)

	for i := 0; i < len(tryAddrs) && err != nil; i++ {
		uri = tryAddrs[i]
		resp, err = client.Get(uri)
	}
	if err != nil {
		//logrus.Warnf("getting %s:%s failed: %v", ip, port, err)
		return false
	}
	defer resp.Body.Close()

	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return false
	}

	body := strings.ToLower(string(b))
	if (strings.Contains(body, "kubernetes") && strings.Contains(body, "pod")) ||
		(strings.Contains(body, "versions") && strings.Contains(body, "serverAddress")) {
		logrus.Infof("uri: %s", uri)
		return true
	}

	return false
}

type ARINResponse struct {
	Net NetJSON `json:"net,omitempty"`
}

type NetJSON struct {
	Organization OrganizationJSON `json:"orgRef,omitempty"`
}

type OrganizationJSON struct {
	Handle    string `json:"@handle,omitempty"`
	Name      string `json:"@name,omitempty"`
	Reference string `json:"$,omitempty"`
}

func getIPInfo(ip string) (b ARINResponse, err error) {
	req, err := http.NewRequest(http.MethodGet, fmt.Sprintf(arinAPIEndpoint, ip), nil)
	if err != nil {
		return b, err
	}
	req.Header.Set("Accept", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return b, err
	}
	defer resp.Body.Close()

	if err := json.NewDecoder(resp.Body).Decode(&b); err != nil {
		return b, err
	}

	return b, nil
}

func inc(ip net.IP) {
	for j := len(ip) - 1; j >= 0; j-- {
		ip[j]++
		if ip[j] > 0 {
			break
		}
	}
}
<|endoftext|>