<commit_before>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package httpauth

import (
	"net/http"
	"net/http/httptest"
	"testing"
)

func TestCreds(t *testing.T) {
	creds := map[string]string{
		"alice": "shhhh",
		"bob":   "",
	}
	tests := []struct {
		username, password string
		valid              bool
	}{
		// Empty, invalid
		{
			"",
			"",
			false,
		},

		// Unknown user
		{
			"cecil",
			"",
			false,
		},

		// Alice, wrong password
		{
			"alice",
			"bob",
			false,
		},

		// Alice, correct password
		{
			"alice",
			"shhhh",
			true,
		},

		// Bob, correct (empty) password
		{
			"bob",
			"",
			true,
		},
	}

	c := Creds(creds)
	for ii, tt := range tests {
		got := c.Check(tt.username, tt.password)
		if got != tt.valid {
			t.Errorf("[%d] c.Check(%#v, %#v) = %#v, expected %#v", ii, tt.username, tt.password, got, tt.valid)
		}
	}

	var nilCreds map[string]string
	c = Creds(nilCreds)

	if c.Check("alice", "") {
		t.Errorf("nil Creds should return false")
	}
}

func TestNone(t *testing.T) {
	if !Skip.Check("", "") {
		t.Errorf("n.Check(\"\", \"\") = false, expected: true")
	}
}

func handlerFuncOK(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(http.StatusText(http.StatusOK)))
	return
}

func testHandlerUnauthorised(t *testing.T, url string, h http.Handler) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		t.Fatalf("unexpected error creating request: %v", err)
	}

	w := httptest.NewRecorder()
	h.ServeHTTP(w, r)

	if w.Code != http.StatusUnauthorized {
		t.Errorf("w.Code = %d, expected: %d", w.Code, http.StatusUnauthorized)
	}

	if w.Header().Get("WWW-Authenticate") != "Basic" {
		t.Errorf("w.Header().Get(\"WWW-Authenticate\") = %s, expected: %s", w.Header().Get("WWW-Authenticate"), "Basic")
	}

	body := w.Body
	if body.String() != http.StatusText(http.StatusUnauthorized) {
		t.Errorf("w.Body = %q, expected: %q", body.String(), http.StatusText(http.StatusUnauthorized))
	}
}

func testHandlerOK(t *testing.T, url string, h http.Handler) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		t.Fatalf("unexpected error creating request: %v", err)
	}

	w := httptest.NewRecorder()
	h.ServeHTTP(w, r)

	if w.Code != http.StatusOK {
		t.Errorf("w.Code = %d, expected: %d", w.Code, http.StatusOK)
	}

	body := w.Body
	if body.String() != http.StatusText(http.StatusOK) {
		t.Errorf("w.Body = %q, expected: %q", body.String(), http.StatusText(http.StatusOK))
	}
}

type fixedChecker bool

func (c fixedChecker) Check(username, password string) bool { return bool(c) }

func TestHandler(t *testing.T) {
	c := fixedChecker(false)
	h := NewHandler(c, http.HandlerFunc(handlerFuncOK))
	testHandlerUnauthorised(t, "/", h)

	c = fixedChecker(true)
	h = NewHandler(c, http.HandlerFunc(handlerFuncOK))
	testHandlerOK(t, "/", h)
}

func TestHandlerFunc(t *testing.T) {
	c := fixedChecker(false)
	h := HandlerFunc(c, handlerFuncOK)
	testHandlerUnauthorised(t, "/", h)

	c = fixedChecker(true)
	h = HandlerFunc(c, handlerFuncOK)
	testHandlerOK(t, "/", h)
}

func TestDefaultHandle(t *testing.T) {
	c := fixedChecker(false)
	HandleFunc(c, "/hfu", handlerFuncOK)
	testHandlerUnauthorised(t, "/hfu", http.DefaultServeMux)

	Handle(c, "/hu", http.HandlerFunc(handlerFuncOK))
	testHandlerUnauthorised(t, "/hu", http.DefaultServeMux)

	c = fixedChecker(true)
	HandleFunc(c, "/hfok", handlerFuncOK)
	testHandlerOK(t, "/hfok", http.DefaultServeMux)

	Handle(c, "/hok", http.HandlerFunc(handlerFuncOK))
	testHandlerOK(t, "/hok", http.DefaultServeMux)
}

func TestServeMux(t *testing.T) {
	c := fixedChecker(false)

	m := http.NewServeMux()
	w := NewServeMux(c, m)
	w.HandleFunc("/f", handlerFuncOK)
	testHandlerUnauthorised(t, "/f", m)

	w.Handle("/h", http.HandlerFunc(handlerFuncOK))
	testHandlerUnauthorised(t, "/h", m)

	c = fixedChecker(true)

	m = http.NewServeMux()
	w = NewServeMux(c, m)
	w.HandleFunc("/f", handlerFuncOK)
	testHandlerOK(t, "/f", m)

	w.Handle("/h", http.HandlerFunc(handlerFuncOK))
	testHandlerOK(t, "/h", m)
}
<commit_msg>update tests to run in seperate pkg<commit_after>// Copyright 2015, David Howden
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package httpauth_test

import (
	"net/http"
	"net/http/httptest"
	"testing"

	. "github.com/dhowden/httpauth"
)

func TestCreds(t *testing.T) {
	creds := map[string]string{
		"alice": "shhhh",
		"bob":   "",
	}
	tests := []struct {
		username, password string
		valid              bool
	}{
		// Empty, invalid
		{
			"",
			"",
			false,
		},

		// Unknown user
		{
			"cecil",
			"",
			false,
		},

		// Alice, wrong password
		{
			"alice",
			"bob",
			false,
		},

		// Alice, correct password
		{
			"alice",
			"shhhh",
			true,
		},

		// Bob, correct (empty) password
		{
			"bob",
			"",
			true,
		},
	}

	c := Creds(creds)
	for ii, tt := range tests {
		got := c.Check(tt.username, tt.password)
		if got != tt.valid {
			t.Errorf("[%d] c.Check(%#v, %#v) = %#v, expected %#v", ii, tt.username, tt.password, got, tt.valid)
		}
	}

	var nilCreds map[string]string
	c = Creds(nilCreds)

	if c.Check("alice", "") {
		t.Errorf("nil Creds should return false")
	}
}

func TestNone(t *testing.T) {
	if !Skip.Check("", "") {
		t.Errorf("n.Check(\"\", \"\") = false, expected: true")
	}
}

func handlerFuncOK(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Write([]byte(http.StatusText(http.StatusOK)))
	return
}

func testHandlerUnauthorised(t *testing.T, url string, h http.Handler) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		t.Fatalf("unexpected error creating request: %v", err)
	}

	w := httptest.NewRecorder()
	h.ServeHTTP(w, r)

	if w.Code != http.StatusUnauthorized {
		t.Errorf("w.Code = %d, expected: %d", w.Code, http.StatusUnauthorized)
	}

	if w.Header().Get("WWW-Authenticate") != "Basic" {
		t.Errorf("w.Header().Get(\"WWW-Authenticate\") = %s, expected: %s", w.Header().Get("WWW-Authenticate"), "Basic")
	}

	body := w.Body
	if body.String() != http.StatusText(http.StatusUnauthorized) {
		t.Errorf("w.Body = %q, expected: %q", body.String(), http.StatusText(http.StatusUnauthorized))
	}
}

func testHandlerOK(t *testing.T, url string, h http.Handler) {
	r, err := http.NewRequest("GET", url, nil)
	if err != nil {
		t.Fatalf("unexpected error creating request: %v", err)
	}

	w := httptest.NewRecorder()
	h.ServeHTTP(w, r)

	if w.Code != http.StatusOK {
		t.Errorf("w.Code = %d, expected: %d", w.Code, http.StatusOK)
	}

	body := w.Body
	if body.String() != http.StatusText(http.StatusOK) {
		t.Errorf("w.Body = %q, expected: %q", body.String(), http.StatusText(http.StatusOK))
	}
}

type fixedChecker bool

func (c fixedChecker) Check(username, password string) bool { return bool(c) }

func TestHandler(t *testing.T) {
	c := fixedChecker(false)
	h := NewHandler(c, http.HandlerFunc(handlerFuncOK))
	testHandlerUnauthorised(t, "/", h)

	c = fixedChecker(true)
	h = NewHandler(c, http.HandlerFunc(handlerFuncOK))
	testHandlerOK(t, "/", h)
}

func TestHandlerFunc(t *testing.T) {
	c := fixedChecker(false)
	h := HandlerFunc(c, handlerFuncOK)
	testHandlerUnauthorised(t, "/", h)

	c = fixedChecker(true)
	h = HandlerFunc(c, handlerFuncOK)
	testHandlerOK(t, "/", h)
}

func TestDefaultHandle(t *testing.T) {
	c := fixedChecker(false)
	HandleFunc(c, "/hfu", handlerFuncOK)
	testHandlerUnauthorised(t, "/hfu", http.DefaultServeMux)

	Handle(c, "/hu", http.HandlerFunc(handlerFuncOK))
	testHandlerUnauthorised(t, "/hu", http.DefaultServeMux)

	c = fixedChecker(true)
	HandleFunc(c, "/hfok", handlerFuncOK)
	testHandlerOK(t, "/hfok", http.DefaultServeMux)

	Handle(c, "/hok", http.HandlerFunc(handlerFuncOK))
	testHandlerOK(t, "/hok", http.DefaultServeMux)
}

func TestServeMux(t *testing.T) {
	c := fixedChecker(false)

	m := http.NewServeMux()
	w := NewServeMux(c, m)
	w.HandleFunc("/f", handlerFuncOK)
	testHandlerUnauthorised(t, "/f", m)

	w.Handle("/h", http.HandlerFunc(handlerFuncOK))
	testHandlerUnauthorised(t, "/h", m)

	c = fixedChecker(true)

	m = http.NewServeMux()
	w = NewServeMux(c, m)
	w.HandleFunc("/f", handlerFuncOK)
	testHandlerOK(t, "/f", m)

	w.Handle("/h", http.HandlerFunc(handlerFuncOK))
	testHandlerOK(t, "/h", m)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"

	humanizepkg "github.com/dustin/go-humanize"
)

func main() {
	var (
		flagComma = flag.Bool("c", false, "")
	)
	flag.Parse()

	if flag.NArg() == 0 {
		s := bufio.NewScanner(os.Stdin)
		for s.Scan() {
			line := s.Text()
			fmt.Println(humanize(line, *flagComma))
		}
		if err := s.Err(); err != nil {
			log.Fatal(err)
		}
		return
	}

	for _, arg := range flag.Args() {
		fmt.Println(humanize(arg, *flagComma))
	}

}

func humanize(s string, comma bool) string {
	if comma {
		i, err := strconv.ParseInt(s, 10, 64)
		if err != nil {
			log.Fatalf("could not parse %v: %v", s, err)
		}
		return humanizepkg.Comma(int64(i))
	}

	i, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		log.Fatalf("could not parse %v: %v", s, err)
	}
	return humanizepkg.Bytes(i)
}
<commit_msg>humanize: minor things<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"

	humanizepkg "github.com/dustin/go-humanize"
)

func main() {
	var (
		flagComma = flag.Bool("c", false, "Use commas after every 3 orders")
	)
	flag.Parse()

	if flag.NArg() != 0 {
		for _, arg := range flag.Args() {
			fmt.Println(humanize(arg, *flagComma))
		}
		return
	}

	s := bufio.NewScanner(os.Stdin)
	for s.Scan() {
		fmt.Println(humanize(s.Text(), *flagComma))
	}
	if err := s.Err(); err != nil {
		log.Fatal(err)
	}
}

func humanize(s string, comma bool) string {
	if comma {
		i, err := strconv.ParseInt(s, 10, 64)
		if err != nil {
			log.Fatalf("could not parse %v: %v", s, err)
		}
		return humanizepkg.Comma(int64(i))
	}

	i, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		log.Fatalf("could not parse %v: %v", s, err)
	}
	return humanizepkg.Bytes(i)
}
<|endoftext|>


<commit_before><commit_msg>Fixed the profileSystemProcessors function so it will filter out CPU information to only process unique CPUs<commit_after><|endoftext|>


<commit_before>package main

import (
	"github.com/pilu/traffic"
)

func indexHandler(w traffic.ResponseWriter, r *traffic.Request) {
	w.Render("index")
}

func relaysHandler(w traffic.ResponseWriter, r *traffic.Request) {
	w.Render("relays")
}

func sync_familyHandler(w traffic.ResponseWriter, r *traffic.Request) {
	w.Render("sync_family")
}

func sync_aboutHandler(w traffic.ResponseWriter, r *traffic.Request) {
	        w.Render("about")
}

func main() {
	router := traffic.New()

	// add a route for each page you add to the site
	// make sure you create a route handler for it
	router.Get("/", indexHandler)
	router.Get("/coldkernel", indexHandler)
	router.Get("/relays", relaysHandler)
	router.Get("/sync_family", sync_familyHandler)
	router.Get("/about", sync_familyHandler)
	router.Run()
}
<commit_msg>Fix tabbing<commit_after>package main

import (
	"github.com/pilu/traffic"
)

func indexHandler(w traffic.ResponseWriter, r *traffic.Request) {
	w.Render("index")
}

func relaysHandler(w traffic.ResponseWriter, r *traffic.Request) {
	w.Render("relays")
}

func sync_familyHandler(w traffic.ResponseWriter, r *traffic.Request) {
	w.Render("sync_family")
}

func sync_aboutHandler(w traffic.ResponseWriter, r *traffic.Request) {
        w.Render("about")
}

func main() {
	router := traffic.New()

	// add a route for each page you add to the site
	// make sure you create a route handler for it
	router.Get("/", indexHandler)
	router.Get("/coldkernel", indexHandler)
	router.Get("/relays", relaysHandler)
	router.Get("/sync_family", sync_familyHandler)
	router.Get("/about", sync_familyHandler)
	router.Run()
}
<|endoftext|>


<commit_before>//  Copyright (c) 2015 Couchbase, Inc.

package gson

import "strconv"
import "sort"

func json2collate(txt string, code []byte, config *Config) (string, int) {
	txt = skipWS(txt, config.ws)
	if len(txt) < 1 {
		panic("collate scanner jsonEmpty")
	}

	n := 0

	if digitCheck[txt[0]] == 1 {
		code[n] = TypeNumber
		n++
		m, remtxt := jsonnum2collate(txt, code[n:], config.nk)
		n += m
		code[n] = Terminator
		n++
		return remtxt, n
	}

	switch txt[0] {
	case 'n':
		if len(txt) >= 4 && txt[:4] == "null" {
			code[n], code[n+1] = TypeNull, Terminator
			return txt[4:], n + 2
		}
		panic("collate scanner expectedNil")

	case 't':
		if len(txt) >= 4 && txt[:4] == "true" {
			code[n], code[n+1] = TypeTrue, Terminator
			return txt[4:], n + 2
		}
		panic("collate scanner expectedTrue")

	case 'f':
		if len(txt) >= 5 && txt[:5] == "false" {
			code[n], code[n+1] = TypeFalse, Terminator
			return txt[5:], n + 2
		}
		panic("collate scanner expectedFalse")

	case '"':
		scratch := stringPool.Get().([]byte)
		defer stringPool.Put(scratch)

		txt, p := scanString(txt, scratch)
		if config.doMissing && MissingLiteral.Equal(bytes2str(scratch[:p])) {
			code[n], code[n+1] = TypeMissing, Terminator
			return txt, n + 2
		}
		code[n] = TypeString
		n++
		n += suffixEncodeString(scratch[:p], code[n:])
		code[n] = Terminator
		n++
		return txt, n

	case '[':
		var x int

		code[n] = TypeArray
		n++
		n_, n__, ln := n, n, 0
		if config.arrayLenPrefix {
			n_, n__ = (n_ + 32), (n__ + 32) // prealloc space for Len encoding
		}

		if txt = skipWS(txt[1:], config.ws); len(txt) == 0 {
			panic("collate scanner expectedCloseArray")

		} else if txt[0] != ']' {
			for {
				txt, x = json2collate(txt, code[n__:], config)
				n__ += x
				ln++
				if txt = skipWS(txt, config.ws); len(txt) == 0 {
					panic("gson scanner expectedCloseArray")
				} else if txt[0] == ',' {
					txt = skipWS(txt[1:], config.ws)
				} else if txt[0] == ']' {
					break
				} else {
					panic("collate scanner expectedCloseArray")
				}
			}
		}
		if config.arrayLenPrefix {
			n += gson2collate(Length(ln), code[n:], config)
			copy(code[n:], code[n_:n__])
			n += (n__ - n_)
		} else {
			n = n__
		}
		code[n] = Terminator
		n++
		return txt[1:], n

	case '{':
		var x int

		code[n] = TypeObj
		n++

		pool := getJsonKeyPool(config.maxKeys)
		altcode, p := pool.codepool.Get().([]byte), 0
		defer pool.codepool.Put(altcode)
		refs, ln := pool.keypool.Get().(kvrefs), 0
		defer pool.keypool.Put(refs)

		if txt = skipWS(txt[1:], config.ws); len(txt) == 0 {
			panic("collate scanner expectedCloseobject")
		} else if txt[0] != '}' && txt[0] != '"' {
			panic("collate scanner expectedKey")
		} else if txt[0] != '}' {
			for {
				// NOTE: empty string is also a valid key
				txt, x = scanString(txt, altcode[p:])
				if txt = skipWS(txt, config.ws); len(txt) == 0 || txt[0] != ':' {
					panic("collate scanner expectedColon")
				}
				key := bytes2str(altcode[p : p+x])
				p += x

				txt = skipWS(txt[1:], config.ws)
				txt, x = json2collate(txt, altcode[p:], config)
				refs[ln] = kvref{key, altcode[p : p+x]}
				p += x
				ln++

				if txt = skipWS(txt, config.ws); len(txt) == 0 {
					panic("collate scanner expectedCloseobject")
				} else if txt[0] == ',' {
					txt = skipWS(txt[1:], config.ws)
				} else if txt[0] == '}' {
					break
				} else {
					panic("collate scanner expectedCloseobject")
				}
			}
			sort.Sort(refs[:ln])
		}
		if config.propertyLenPrefix {
			n += gson2collate(Length(ln), code[n:], config)
		}
		for j := 0; j < ln; j++ {
			kv := refs[j]
			n += gson2collate(kv.key, code[n:], config) // encode key
			copy(code[n:], kv.code)
			n += len(kv.code)
		}
		code[n] = Terminator
		n++
		return txt[1:], n
	}
	panic("collate scanner expectedToken")
}

func jsonnum2collate(txt string, code []byte, nk NumberKind) (int, string) {
	s, e, l := 0, 1, len(txt)
	if len(txt) > 1 {
		for ; e < l && intCheck[txt[e]] == 1; e++ {
		}
	}
	f, err := strconv.ParseFloat(txt[s:e], 64)
	if err != nil {
		panic(err)
	}
	n := normalizeFloat(f, code, nk)
	return n, txt[e:]
}

func collate2json(code []byte, text []byte, config *Config) (int, int) {
	if len(code) == 0 {
		return 0, 0
	}
	var scratch [64]byte
	n, m := 1, 0
	switch code[0] {
	case TypeMissing:
		copy(text, MissingLiteral)
		return n + 1, m + len(MissingLiteral)

	case TypeNull:
		copy(text, "null")
		return n + 1, m + 4

	case TypeTrue:
		copy(text, "true")
		return n + 1, m + 4

	case TypeFalse:
		copy(text, "false")
		return n + 1, m + 5

	case TypeNumber:
		x := getDatum(code[n:])
		y := denormalizeFloatTojson(code[n:n+x-1], text, config.nk)
		return n + x, m + y

	case TypeString:
		scratch := stringPool.Get().([]byte)
		defer stringPool.Put(scratch)
		x, y := suffixDecodeString(code[n:], scratch)
		config.buf.Reset()
		if err := config.enc.Encode(bytes2str(scratch[:y])); err != nil {
			panic(err)
		}
		s := config.buf.Bytes()
		m += copy(text[m:], s[:len(s)-1]) // -1 to strip \n
		return n + x, m

	case TypeArray:
		if config.arrayLenPrefix {
			x := getDatum(code[n:])
			collated2Int(code[n:n+x-1], scratch[:])
			n += x
		}
		text[m] = '['
		m++
		for code[n] != Terminator {
			x, y := collate2json(code[n:], text[m:], config)
			n += x
			m += y
			text[m] = ','
			m++
		}
		n++ // skip terminator
		if text[m-1] == ',' {
			text[m-1] = ']'
		} else {
			text[m] = ']'
			m++
		}
		return n, m

	case TypeObj:
		if config.propertyLenPrefix {
			x := getDatum(code[n:])
			collated2Int(code[n:n+x-1], scratch[:])
			n += x
		}
		text[m] = '{'
		m++
		for code[n] != Terminator {
			x, y := collate2json(code[n:], text[m:], config)
			n, m = n+x, m+y
			text[m] = ':'
			m++
			x, y = collate2json(code[n:], text[m:], config)
			n, m = n+x, m+y
			text[m] = ','
			m++
		}
		n++ // skip terminator
		if text[m-1] == ',' {
			text[m-1] = '}'
		} else {
			text[m] = '}'
			m++
		}
		return n, m
	}
	panic("collate decode to json invalid binary")
}
<commit_msg>avoid an allocation when converting collate-to-json.<commit_after>//  Copyright (c) 2015 Couchbase, Inc.

package gson

import "strconv"
import "sort"

func json2collate(txt string, code []byte, config *Config) (string, int) {
	txt = skipWS(txt, config.ws)
	if len(txt) < 1 {
		panic("collate scanner jsonEmpty")
	}

	n := 0

	if digitCheck[txt[0]] == 1 {
		code[n] = TypeNumber
		n++
		m, remtxt := jsonnum2collate(txt, code[n:], config.nk)
		n += m
		code[n] = Terminator
		n++
		return remtxt, n
	}

	switch txt[0] {
	case 'n':
		if len(txt) >= 4 && txt[:4] == "null" {
			code[n], code[n+1] = TypeNull, Terminator
			return txt[4:], n + 2
		}
		panic("collate scanner expectedNil")

	case 't':
		if len(txt) >= 4 && txt[:4] == "true" {
			code[n], code[n+1] = TypeTrue, Terminator
			return txt[4:], n + 2
		}
		panic("collate scanner expectedTrue")

	case 'f':
		if len(txt) >= 5 && txt[:5] == "false" {
			code[n], code[n+1] = TypeFalse, Terminator
			return txt[5:], n + 2
		}
		panic("collate scanner expectedFalse")

	case '"':
		scratch := stringPool.Get().([]byte)
		defer stringPool.Put(scratch)

		txt, p := scanString(txt, scratch)
		if config.doMissing && MissingLiteral.Equal(bytes2str(scratch[:p])) {
			code[n], code[n+1] = TypeMissing, Terminator
			return txt, n + 2
		}
		code[n] = TypeString
		n++
		n += suffixEncodeString(scratch[:p], code[n:])
		code[n] = Terminator
		n++
		return txt, n

	case '[':
		var x int

		code[n] = TypeArray
		n++
		n_, n__, ln := n, n, 0
		if config.arrayLenPrefix {
			n_, n__ = (n_ + 32), (n__ + 32) // prealloc space for Len encoding
		}

		if txt = skipWS(txt[1:], config.ws); len(txt) == 0 {
			panic("collate scanner expectedCloseArray")

		} else if txt[0] != ']' {
			for {
				txt, x = json2collate(txt, code[n__:], config)
				n__ += x
				ln++
				if txt = skipWS(txt, config.ws); len(txt) == 0 {
					panic("gson scanner expectedCloseArray")
				} else if txt[0] == ',' {
					txt = skipWS(txt[1:], config.ws)
				} else if txt[0] == ']' {
					break
				} else {
					panic("collate scanner expectedCloseArray")
				}
			}
		}
		if config.arrayLenPrefix {
			n += gson2collate(Length(ln), code[n:], config)
			copy(code[n:], code[n_:n__])
			n += (n__ - n_)
		} else {
			n = n__
		}
		code[n] = Terminator
		n++
		return txt[1:], n

	case '{':
		var x int

		code[n] = TypeObj
		n++

		pool := getJsonKeyPool(config.maxKeys)
		altcode, p := pool.codepool.Get().([]byte), 0
		defer pool.codepool.Put(altcode)
		refs, ln := pool.keypool.Get().(kvrefs), 0
		defer pool.keypool.Put(refs)

		if txt = skipWS(txt[1:], config.ws); len(txt) == 0 {
			panic("collate scanner expectedCloseobject")
		} else if txt[0] != '}' && txt[0] != '"' {
			panic("collate scanner expectedKey")
		} else if txt[0] != '}' {
			for {
				// NOTE: empty string is also a valid key
				txt, x = scanString(txt, altcode[p:])
				if txt = skipWS(txt, config.ws); len(txt) == 0 || txt[0] != ':' {
					panic("collate scanner expectedColon")
				}
				key := bytes2str(altcode[p : p+x])
				p += x

				txt = skipWS(txt[1:], config.ws)
				txt, x = json2collate(txt, altcode[p:], config)
				refs[ln] = kvref{key, altcode[p : p+x]}
				p += x
				ln++

				if txt = skipWS(txt, config.ws); len(txt) == 0 {
					panic("collate scanner expectedCloseobject")
				} else if txt[0] == ',' {
					txt = skipWS(txt[1:], config.ws)
				} else if txt[0] == '}' {
					break
				} else {
					panic("collate scanner expectedCloseobject")
				}
			}
			sort.Sort(refs[:ln])
		}
		if config.propertyLenPrefix {
			n += gson2collate(Length(ln), code[n:], config)
		}
		for j := 0; j < ln; j++ {
			kv := refs[j]
			n += gson2collate(kv.key, code[n:], config) // encode key
			copy(code[n:], kv.code)
			n += len(kv.code)
		}
		code[n] = Terminator
		n++
		return txt[1:], n
	}
	panic("collate scanner expectedToken")
}

func jsonnum2collate(txt string, code []byte, nk NumberKind) (int, string) {
	s, e, l := 0, 1, len(txt)
	if len(txt) > 1 {
		for ; e < l && intCheck[txt[e]] == 1; e++ {
		}
	}
	f, err := strconv.ParseFloat(txt[s:e], 64)
	if err != nil {
		panic(err)
	}
	n := normalizeFloat(f, code, nk)
	return n, txt[e:]
}

func collate2json(code []byte, text []byte, config *Config) (int, int) {
	if len(code) == 0 {
		return 0, 0
	}
	var scratch [64]byte
	n, m := 1, 0
	switch code[0] {
	case TypeMissing:
		copy(text, MissingLiteral)
		return n + 1, m + len(MissingLiteral)

	case TypeNull:
		copy(text, "null")
		return n + 1, m + 4

	case TypeTrue:
		copy(text, "true")
		return n + 1, m + 4

	case TypeFalse:
		copy(text, "false")
		return n + 1, m + 5

	case TypeNumber:
		x := getDatum(code[n:])
		y := denormalizeFloatTojson(code[n:n+x-1], text, config.nk)
		return n + x, m + y

	case TypeString:
		block := stringPool.Get()
		scratch := block.([]byte)
		defer stringPool.Put(block)
		x, y := suffixDecodeString(code[n:], scratch[:])
		config.buf.Reset()
		if err := config.enc.Encode(bytes2str(scratch[:y])); err != nil {
			panic(err)
		}
		s := config.buf.Bytes()
		m += copy(text[m:], s[:len(s)-1]) // -1 to strip \n
		return n + x, m

	case TypeArray:
		if config.arrayLenPrefix {
			x := getDatum(code[n:])
			collated2Int(code[n:n+x-1], scratch[:])
			n += x
		}
		text[m] = '['
		m++
		for code[n] != Terminator {
			x, y := collate2json(code[n:], text[m:], config)
			n += x
			m += y
			text[m] = ','
			m++
		}
		n++ // skip terminator
		if text[m-1] == ',' {
			text[m-1] = ']'
		} else {
			text[m] = ']'
			m++
		}
		return n, m

	case TypeObj:
		if config.propertyLenPrefix {
			x := getDatum(code[n:])
			collated2Int(code[n:n+x-1], scratch[:])
			n += x
		}
		text[m] = '{'
		m++
		for code[n] != Terminator {
			x, y := collate2json(code[n:], text[m:], config)
			n, m = n+x, m+y
			text[m] = ':'
			m++
			x, y = collate2json(code[n:], text[m:], config)
			n, m = n+x, m+y
			text[m] = ','
			m++
		}
		n++ // skip terminator
		if text[m-1] == ',' {
			text[m-1] = '}'
		} else {
			text[m] = '}'
			m++
		}
		return n, m
	}
	panic("collate decode to json invalid binary")
}
<|endoftext|>


<commit_before>package main

import (
	"strings"

	"github.com/docker/docker/pkg/integration/checker"
	"github.com/docker/docker/pkg/stringid"
	"github.com/go-check/check"
)

func (s *DockerSuite) TestRenameStoppedContainer(c *check.C) {
	out, _ := dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh")

	cleanedContainerID := strings.TrimSpace(out)
	dockerCmd(c, "wait", cleanedContainerID)

	name := inspectField(c, cleanedContainerID, "Name")
	newName := "new_name" + stringid.GenerateNonCryptoID()
	dockerCmd(c, "rename", "first_name", newName)

	name = inspectField(c, cleanedContainerID, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))

}

func (s *DockerSuite) TestRenameRunningContainer(c *check.C) {
	out, _ := dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh")

	newName := "new_name" + stringid.GenerateNonCryptoID()
	cleanedContainerID := strings.TrimSpace(out)
	dockerCmd(c, "rename", "first_name", newName)

	name := inspectField(c, cleanedContainerID, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))
}

func (s *DockerSuite) TestRenameRunningContainerAndReuse(c *check.C) {
	out, _ := runSleepingContainer(c, "--name", "first_name")
	c.Assert(waitRun("first_name"), check.IsNil)

	newName := "new_name"
	ContainerID := strings.TrimSpace(out)
	dockerCmd(c, "rename", "first_name", newName)

	name := inspectField(c, ContainerID, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container"))

	out, _ = runSleepingContainer(c, "--name", "first_name")
	c.Assert(waitRun("first_name"), check.IsNil)
	newContainerID := strings.TrimSpace(out)
	name = inspectField(c, newContainerID, "Name")
	c.Assert(name, checker.Equals, "/first_name", check.Commentf("Failed to reuse container name"))
}

func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
	dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh")

	newName := "new_name" + stringid.GenerateNonCryptoID()
	dockerCmd(c, "rename", "first_name", newName)

	name := inspectField(c, newName, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))

	name, err := inspectFieldWithError("first_name", "Name")
	c.Assert(err, checker.NotNil, check.Commentf(name))
	c.Assert(err.Error(), checker.Contains, "No such image or container: first_name")
}

func (s *DockerSuite) TestRenameInvalidName(c *check.C) {
	runSleepingContainer(c, "--name", "myname")

	out, _, err := dockerCmdWithError("rename", "myname", "new:invalid")
	c.Assert(err, checker.NotNil, check.Commentf("Renaming container to invalid name should have failed: %s", out))
	c.Assert(out, checker.Contains, "Invalid container name", check.Commentf("%v", err))

	out, _, err = dockerCmdWithError("rename", "myname", "")
	c.Assert(err, checker.NotNil, check.Commentf("Renaming container to invalid name should have failed: %s", out))
	c.Assert(out, checker.Contains, "\"docker rename\" requires exactly 2 argument(s).", check.Commentf("%v", err))

	out, _, err = dockerCmdWithError("rename", "", "newname")
	c.Assert(err, checker.NotNil, check.Commentf("Renaming container with empty name should have failed: %s", out))
	c.Assert(out, checker.Contains, "\"docker rename\" requires exactly 2 argument(s).", check.Commentf("%v", err))

	out, _ = dockerCmd(c, "ps", "-a")
	c.Assert(out, checker.Contains, "myname", check.Commentf("Output of docker ps should have included 'myname': %s", out))
}

func (s *DockerSuite) TestRenameAnonymousContainer(c *check.C) {
	testRequires(c, DaemonIsLinux)

	dockerCmd(c, "network", "create", "network1")
	out, _ := dockerCmd(c, "create", "-it", "--net", "network1", "busybox", "top")

	anonymousContainerID := strings.TrimSpace(out)

	dockerCmd(c, "rename", anonymousContainerID, "container1")
	dockerCmd(c, "start", "container1")

	count := "-c"
	if daemonPlatform == "windows" {
		count = "-n"
	}

	_, _, err := dockerCmdWithError("run", "--net", "network1", "busybox", "ping", count, "1", "container1")
	c.Assert(err, check.IsNil, check.Commentf("Embedded DNS lookup fails after renaming anonymous container: %v", err))
}
<commit_msg>Fix TestRenameInvalidName<commit_after>package main

import (
	"strings"

	"github.com/docker/docker/pkg/integration/checker"
	"github.com/docker/docker/pkg/stringid"
	"github.com/go-check/check"
)

func (s *DockerSuite) TestRenameStoppedContainer(c *check.C) {
	out, _ := dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh")

	cleanedContainerID := strings.TrimSpace(out)
	dockerCmd(c, "wait", cleanedContainerID)

	name := inspectField(c, cleanedContainerID, "Name")
	newName := "new_name" + stringid.GenerateNonCryptoID()
	dockerCmd(c, "rename", "first_name", newName)

	name = inspectField(c, cleanedContainerID, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))

}

func (s *DockerSuite) TestRenameRunningContainer(c *check.C) {
	out, _ := dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh")

	newName := "new_name" + stringid.GenerateNonCryptoID()
	cleanedContainerID := strings.TrimSpace(out)
	dockerCmd(c, "rename", "first_name", newName)

	name := inspectField(c, cleanedContainerID, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))
}

func (s *DockerSuite) TestRenameRunningContainerAndReuse(c *check.C) {
	out, _ := runSleepingContainer(c, "--name", "first_name")
	c.Assert(waitRun("first_name"), check.IsNil)

	newName := "new_name"
	ContainerID := strings.TrimSpace(out)
	dockerCmd(c, "rename", "first_name", newName)

	name := inspectField(c, ContainerID, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container"))

	out, _ = runSleepingContainer(c, "--name", "first_name")
	c.Assert(waitRun("first_name"), check.IsNil)
	newContainerID := strings.TrimSpace(out)
	name = inspectField(c, newContainerID, "Name")
	c.Assert(name, checker.Equals, "/first_name", check.Commentf("Failed to reuse container name"))
}

func (s *DockerSuite) TestRenameCheckNames(c *check.C) {
	dockerCmd(c, "run", "--name", "first_name", "-d", "busybox", "sh")

	newName := "new_name" + stringid.GenerateNonCryptoID()
	dockerCmd(c, "rename", "first_name", newName)

	name := inspectField(c, newName, "Name")
	c.Assert(name, checker.Equals, "/"+newName, check.Commentf("Failed to rename container %s", name))

	name, err := inspectFieldWithError("first_name", "Name")
	c.Assert(err, checker.NotNil, check.Commentf(name))
	c.Assert(err.Error(), checker.Contains, "No such image or container: first_name")
}

func (s *DockerSuite) TestRenameInvalidName(c *check.C) {
	runSleepingContainer(c, "--name", "myname")

	out, _, err := dockerCmdWithError("rename", "myname", "new:invalid")
	c.Assert(err, checker.NotNil, check.Commentf("Renaming container to invalid name should have failed: %s", out))
	c.Assert(out, checker.Contains, "Invalid container name", check.Commentf("%v", err))

	out, _, err = dockerCmdWithError("rename", "myname")
	c.Assert(err, checker.NotNil, check.Commentf("Renaming container to invalid name should have failed: %s", out))
	c.Assert(out, checker.Contains, "requires exactly 2 argument(s).", check.Commentf("%v", err))

	out, _, err = dockerCmdWithError("rename", "myname", "")
	c.Assert(err, checker.NotNil, check.Commentf("Renaming container to invalid name should have failed: %s", out))
	c.Assert(out, checker.Contains, "may be empty", check.Commentf("%v", err))

	out, _, err = dockerCmdWithError("rename", "", "newname")
	c.Assert(err, checker.NotNil, check.Commentf("Renaming container with empty name should have failed: %s", out))
	c.Assert(out, checker.Contains, "may be empty", check.Commentf("%v", err))

	out, _ = dockerCmd(c, "ps", "-a")
	c.Assert(out, checker.Contains, "myname", check.Commentf("Output of docker ps should have included 'myname': %s", out))
}

func (s *DockerSuite) TestRenameAnonymousContainer(c *check.C) {
	testRequires(c, DaemonIsLinux)

	dockerCmd(c, "network", "create", "network1")
	out, _ := dockerCmd(c, "create", "-it", "--net", "network1", "busybox", "top")

	anonymousContainerID := strings.TrimSpace(out)

	dockerCmd(c, "rename", anonymousContainerID, "container1")
	dockerCmd(c, "start", "container1")

	count := "-c"
	if daemonPlatform == "windows" {
		count = "-n"
	}

	_, _, err := dockerCmdWithError("run", "--net", "network1", "busybox", "ping", count, "1", "container1")
	c.Assert(err, check.IsNil, check.Commentf("Embedded DNS lookup fails after renaming anonymous container: %v", err))
}
<|endoftext|>


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

package queries_service

import (
	"encoding/json"
	"errors"
	"time"

	"github.com/aleasoluciones/simpleamqp"
)

const (
	AMQP_RECEIVE_TIMEOUT = 30 * time.Minute
	RESPONSES_QUEUE      = "queries_responses"
)

type Result interface{}

type QueriesService interface {
	Query(topic string, criteria Criteria) (Result, error)
}

func NewQueriesService(amqpPublisher simpleamqp.AMQPPublisher, amqpConsumer simpleamqp.AMQPConsumer, idsRepository IdsRepository, exchange string, timeout time.Duration) QueriesService {
	service := queriesService{
		amqpConsumer:  amqpConsumer,
		amqpPublisher: amqpPublisher,
		idsRepository: idsRepository,
		exchange:      exchange,
		queryTimeout:  timeout,

		queries:   make(chan query),
		responses: make(chan ResponseMessage),
	}

	go service.dispatch()
	go service.receiveResponses()

	return &service
}

type queriesService struct {
	amqpConsumer  simpleamqp.AMQPConsumer
	amqpPublisher simpleamqp.AMQPPublisher
	idsRepository IdsRepository
	exchange      string
	queryTimeout  time.Duration

	queries   chan query
	responses chan ResponseMessage
}

type query struct {
	RoutingKey     string
	CriteriaValues Criteria
	Responses      chan ResponseMessage
}

type amqpQueryMessage struct {
	Id             Id       `json:"id"`
	CriteriaValues Criteria `json:"criteria"`
}

type ResponseMessage struct {
	Id      Id
	Message interface{}
}

func (service *queriesService) receiveResponses() {
	amqpResponses := service.amqpConsumer.Receive(
		service.exchange,
		[]string{"queries.response"},
		RESPONSES_QUEUE,
		simpleamqp.QueueOptions{Durable: false, Delete: true, Exclusive: true},
		AMQP_RECEIVE_TIMEOUT)

	var deserialized map[string]interface{}

	for message := range amqpResponses {
		_ = json.Unmarshal([]byte(message.Body), &deserialized)

		service.responses <- ResponseMessage{
			Id:      Id(deserialized["id"].(string)),
			Message: deserialized["result"],
		}
	}
}

func (service *queriesService) dispatch() {
	var id Id
	var responses chan ResponseMessage
	var found bool

	queryResponses := map[Id]chan ResponseMessage{}

	for {
		select {
		case query := <-service.queries:
			id = service.idsRepository.Next()
			queryResponses[id] = query.Responses
			service.publishQuery(id, query)
		case response := <-service.responses:
			responses, found = queryResponses[response.Id]
			if found {
				responses <- response
			}
		}
	}
}

func (service *queriesService) publishQuery(id Id, query query) {
	messageToSendJson, _ := json.Marshal(amqpQueryMessage{
		Id:             id,
		CriteriaValues: query.CriteriaValues,
	})

	service.amqpPublisher.Publish("queries.query."+query.RoutingKey, messageToSendJson)
}

type Criteria map[string]string

func (service *queriesService) Query(topic string, criteria Criteria) (Result, error) {
	responses := make(chan ResponseMessage)
	service.queries <- query{
		RoutingKey:     topic,
		CriteriaValues: criteria,
		Responses:      responses,
	}

	timeoutTicker := time.NewTicker(service.queryTimeout)
	defer timeoutTicker.Stop()
	afterTimeout := timeoutTicker.C

	select {
	case response := <-responses:
		return response.Message, nil
	case <-afterTimeout:
		return nil, errors.New("Timeout")
	}
}
<commit_msg>Type to deserialize amqp query responses<commit_after>// Copyright 2015 The http2amqp Authors. All rights reserved.  Use of this
// source code is governed by a MIT-style license that can be found in the
// LICENSE file.

package queries_service

import (
	"encoding/json"
	"errors"
	"time"

	"github.com/aleasoluciones/simpleamqp"
)

const (
	AMQP_RECEIVE_TIMEOUT = 30 * time.Minute
	RESPONSES_QUEUE      = "queries_responses"
)

type Result interface{}

type QueriesService interface {
	Query(topic string, criteria Criteria) (Result, error)
}

func NewQueriesService(amqpPublisher simpleamqp.AMQPPublisher, amqpConsumer simpleamqp.AMQPConsumer, idsRepository IdsRepository, exchange string, timeout time.Duration) QueriesService {
	service := queriesService{
		amqpConsumer:  amqpConsumer,
		amqpPublisher: amqpPublisher,
		idsRepository: idsRepository,
		exchange:      exchange,
		queryTimeout:  timeout,

		queries:   make(chan query),
		responses: make(chan ResponseMessage),
	}

	go service.dispatch()
	go service.receiveResponses()

	return &service
}

type queriesService struct {
	amqpConsumer  simpleamqp.AMQPConsumer
	amqpPublisher simpleamqp.AMQPPublisher
	idsRepository IdsRepository
	exchange      string
	queryTimeout  time.Duration

	queries   chan query
	responses chan ResponseMessage
}

type query struct {
	RoutingKey     string
	CriteriaValues Criteria
	Responses      chan ResponseMessage
}

type amqpQueryMessage struct {
	Id             Id       `json:"id"`
	CriteriaValues Criteria `json:"criteria"`
}

type amqpResponseMessage struct {
	Id     Id     `json:"id"`
	Result Result `json:"result"`
}

type ResponseMessage struct {
	Id      Id
	Message interface{}
}

func (service *queriesService) receiveResponses() {
	amqpResponses := service.amqpConsumer.Receive(
		service.exchange,
		[]string{"queries.response"},
		RESPONSES_QUEUE,
		simpleamqp.QueueOptions{Durable: false, Delete: true, Exclusive: true},
		AMQP_RECEIVE_TIMEOUT)

	var deserialized amqpResponseMessage

	for message := range amqpResponses {
		_ = json.Unmarshal([]byte(message.Body), &deserialized)

		service.responses <- ResponseMessage{
			Id:      deserialized.Id,
			Message: deserialized.Result,
		}
	}
}

func (service *queriesService) dispatch() {
	var id Id
	var responses chan ResponseMessage
	var found bool

	queryResponses := map[Id]chan ResponseMessage{}

	for {
		select {
		case query := <-service.queries:
			id = service.idsRepository.Next()
			queryResponses[id] = query.Responses
			service.publishQuery(id, query)
		case response := <-service.responses:
			responses, found = queryResponses[response.Id]
			if found {
				responses <- response
			}
		}
	}
}

func (service *queriesService) publishQuery(id Id, query query) {
	messageToSendJson, _ := json.Marshal(amqpQueryMessage{
		Id:             id,
		CriteriaValues: query.CriteriaValues,
	})

	service.amqpPublisher.Publish("queries.query."+query.RoutingKey, messageToSendJson)
}

type Criteria map[string]string

func (service *queriesService) Query(topic string, criteria Criteria) (Result, error) {
	responses := make(chan ResponseMessage)
	service.queries <- query{
		RoutingKey:     topic,
		CriteriaValues: criteria,
		Responses:      responses,
	}

	timeoutTicker := time.NewTicker(service.queryTimeout)
	defer timeoutTicker.Stop()
	afterTimeout := timeoutTicker.C

	select {
	case response := <-responses:
		return response.Message, nil
	case <-afterTimeout:
		return nil, errors.New("Timeout")
	}
}
<|endoftext|>


<commit_before>package randHashGenerator

import (
	"crypto/rand"
	"log"
)

type HashGenerator struct {
	hashGetter chan string
	length     int
}

func (this *HashGenerator) init() {
	go func() {

		for {
			str := ""

			for len(str) < this.length {
				c := 10
				bArr := make([]byte, c)
				_, err := rand.Read(bArr)
				if err != nil {
					log.Println("error:", err)
					break
				}

				for _, b := range bArr {
					if len(str) == this.length {
						break
					}

					/**
					 * Each byte will be in [0, 256), but we only care about:
					 *
					 * [48, 57]     0-9
					 * [65, 90]     A-Z
					 * [97, 122]    a-z
					 *
					 * Which means that the highest bit will always be zero, since the last byte with high bit
					 * zero is 01111111 = 127 which is higher than 122. Lower our odds of having to re-roll a byte by
					 * dividing by two (right bit shift of 1).
					 */

					b = b >> 1

					// The byte is any of        0-9                  A-Z                      a-z
					byteIsAllowable := (b >= 48 && b <= 57) || (b >= 65 && b <= 90) || (b >= 97 && b <= 122)

					if byteIsAllowable {
						str += string(b)
					}
				}

			}

			this.hashGetter <- str
		}
	}()
}

func (this *HashGenerator) Get() string {
	return <-this.hashGetter
}
<commit_msg>modified var type<commit_after>package randHashGenerator

import (
	"crypto/rand"
	"log"
)

type HashGenerator struct {
	HashGetter chan string
	Length     int
}

func (this *HashGenerator) Init() {
	go func() {

		for {
			str := ""

			for len(str) < this.Length {
				c := 10
				bArr := make([]byte, c)
				_, err := rand.Read(bArr)
				if err != nil {
					log.Println("error:", err)
					break
				}

				for _, b := range bArr {
					if len(str) == this.Length {
						break
					}

					/**
					 * Each byte will be in [0, 256), but we only care about:
					 *
					 * [48, 57]     0-9
					 * [65, 90]     A-Z
					 * [97, 122]    a-z
					 *
					 * Which means that the highest bit will always be zero, since the last byte with high bit
					 * zero is 01111111 = 127 which is higher than 122. Lower our odds of having to re-roll a byte by
					 * dividing by two (right bit shift of 1).
					 */

					b = b >> 1

					// The byte is any of        0-9                  A-Z                      a-z
					byteIsAllowable := (b >= 48 && b <= 57) || (b >= 65 && b <= 90) || (b >= 97 && b <= 122)

					if byteIsAllowable {
						str += string(b)
					}
				}

			}

			this.HashGetter <- str
		}
	}()
}

func (this *HashGenerator) Get() string {
	return <-this.HashGetter
}
<|endoftext|>


<commit_before>//
package engine

import (
	"archive/tar"
	"bytes"
	"crypto/md5"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"time"

	api "github.com/nanobox-io/nanobox-api-client"
	"github.com/nanobox-io/nanobox-golang-stylish"
	"github.com/spf13/cobra"

	"github.com/nanobox-io/nanobox/config"
	engineutil "github.com/nanobox-io/nanobox/util/engine"
	fileutil "github.com/nanobox-io/nanobox/util/file"
	s3util "github.com/nanobox-io/nanobox/util/s3"
)

var tw *tar.Writer

//
var publishCmd = &cobra.Command{
	Use:   "publish",
	Short: "Publishes an engine to nanobox.io",
	Long:  ``,

	Run: publish,
}

// publish
func publish(ccmd *cobra.Command, args []string) {
	stylish.Header("publishing engine")

	//
	api.UserSlug, api.AuthToken = Auth.Authenticate()

	// create a new release
	fmt.Printf(stylish.Bullet("Creating release..."))
	release := &api.EngineRelease{}

	// create an annonymous struct to hold data that doesn't relate to a release but
	// is needed as part of the publish process
	opts := &struct {
		Generic  bool     `json:"generic"`
		Language string   `json:"language"`
		Overlays []string `json:"overlays"`
	}{}

	// ensure there is an Enginefile
	if _, err := os.Stat("./Enginefile"); err != nil {
		fmt.Printf("Enginefile not found. Be sure to publish from a project directory. Exiting...\n")
		os.Exit(1)
	}

	// parse the ./Enginefile into the new release
	if err := Config.ParseConfig("./Enginefile", release); err != nil {
		fmt.Printf("Nanobox failed to parse your Enginefile. Please ensure it is valid YAML and try again.\n")
		os.Exit(1)
	}

	// parse the ./Enginefile again to get the remaining fields
	if err := Config.ParseConfig("./Enginefile", opts); err != nil {
		fmt.Printf("Nanobox failed to parse your Enginefile. Please ensure it is valid YAML and try again.\n")
		os.Exit(1)
	}

	fmt.Printf(stylish.Bullet("Verifying engine is publishable..."))

	// determine if any required fields (name, version, language, summary) are missing,
	// if any are found to be missing exit 1
	// NOTE: I do this using fallthrough for asthetics onlye. The message is generic
	// enough that all cases will return the same message, and this looks better than
	// a single giant case (var == "" || var == "" || ...)
	switch {
	case opts.Language == "":
		fallthrough
	case release.Name == "":
		fallthrough
	case release.Summary == "":
		fallthrough
	case release.Version == "":
		fmt.Printf(stylish.Error("required fields missing", `Your Enginefile is missing one or more of the following required fields for publishing:

  name:      # the name of your project
  version:   # the current version of the project
  language:  # the lanauge (ruby, golang, etc.) of the engine
  summary:   # a 140 character summary of the project

Please ensure all required fields are provided and try again.`))

		os.Exit(1)
	}

	// attempt to read a README.md file and add it to the release...
	b, err := ioutil.ReadFile("./README.md")
	if err != nil {

		// this only fails if the file is not found, EOF is not an error. If no Readme
		// is found exit 1
		fmt.Printf(stylish.Error("missing readme", "Your engine is missing a README.md file. This file is required for publishing, as it is the only way for you to communicate how to use your engine. Please add a README.md and try again."))
		os.Exit(1)
	}

	//
	release.Readme = string(b)

	// check to see if the engine already exists on nanobox.io
	fmt.Printf(stylish.Bullet("Checking for existing engine on nanobox.io"))
	engine, err := api.GetEngine(api.UserSlug, release.Name)

	// if no engine exists, create a new one
	if err != nil {

		// if no engine is found create one
		if apiErr, _ := err.(api.APIError); apiErr.Code == 404 {

			fmt.Printf(stylish.SubTaskStart("Creating new engine on nanobox.io"))

			//
			engine = &api.Engine{
				Generic:      opts.Generic,
				LanguageName: opts.Language,
				Name:         release.Name,
			}

			//
			if _, err := api.CreateEngine(engine); err != nil {
				fmt.Printf(stylish.ErrBullet("Unable to create engine (%v).", err))
				os.Exit(1)
			}

			// wait until engine has been successfuly created before uploading to s3
			for {
				fmt.Print(".")

				p, err := api.GetEngine(api.UserSlug, release.Name)
				if err != nil {
					Config.Fatal("[commands/publish] api.GetEngine failed", err.Error())
				}

				// once the engine is "active", break
				if p.State == "active" {
					break
				}

				//
				time.Sleep(1000 * time.Millisecond)
			}

			// generically handle any other errors
		} else {
			Config.Fatal("[commands/publish] api.GetEngine failed", err.Error())
		}

		stylish.Success()
	}

	// create a meta.json file where we can add any extra data we might need; since
	// this is only used for internal purposes the file is removed once we're done
	// with it
	meta, err := os.Create("./meta.json")
	if err != nil {
		Config.Fatal("[commands/publish] os.Create() failed", err.Error())
	}
	defer meta.Close()
	defer os.Remove(meta.Name())

	// add any custom info to the metafile
	meta.WriteString(fmt.Sprintf(`{"engine_id": "%s"}`, engine.ID))

	// this is our predefined list of everything that gets archived as part of the
	// engine being published
	files := map[string][]string{
		"required": []string{"./bin", "./Enginefile", "./meta.json"},
		"optional": []string{"./lib", "./templates", "./files"},
	}

	// check to ensure no required files are missing
	for k, v := range files {
		if k == "required" {
			for _, f := range v {
				if _, err := os.Stat(f); err != nil {
					fmt.Printf(stylish.Error("required files missing", "Your Engine is missing one or more required files for publishing. Please read the following documentation to ensure all required files are included and try again.:\n\ndocs.nanobox.io/engines/project-creation/#example-engine-file-structure\n"))
					os.Exit(1)
				}
			}
		}
	}

	// create the temp engines folder for building the tarball
	tarPath := filepath.Join(config.EnginesDir, release.Name)
	if err := os.Mkdir(tarPath, 0755); err != nil {
		Config.Fatal("[commands/engine/publish] os.Create() failed", err.Error())
	}

	// remove tarDir once published
	defer func() {
		if err := os.RemoveAll(tarPath); err != nil {
			os.Stderr.WriteString(stylish.ErrBullet("Failed to remove '%v'...", tarPath))
		}
	}()

	// parse the ./Enginefile again to get the overlays
	if err := Config.ParseConfig("./Enginefile", opts); err != nil {
		fmt.Printf("Nanobox failed to parse your Enginefile. Please ensure it is valid YAML and try again.\n")
		os.Exit(1)
	}

	// iterate through each overlay fetching it and untaring to the tar path
	for _, overlay := range opts.Overlays {
		engineutil.GetOverlay(overlay, tarPath)
	}

	// range over each file from each file type, building the final list of files
	// to be tarballed
	for _, v := range files {
		for _, f := range v {

			// not handling error here because an error simply means the file doesn't
			// exist and therefor wont be copied to the final tarball
			fileutil.Copy(f, tarPath)
		}
	}

	// create an empty buffer for writing the file contents to for the subsequent
	// upload
	archive := bytes.NewBuffer(nil)

	//
	h := md5.New()

	//
	if err := fileutil.Tar(tarPath, archive, h); err != nil {
		Config.Fatal("[commands/engine/publish] file.Tar() failed", err.Error())
	}

	// add the checksum for the new release once its finished being archived
	release.Checksum = fmt.Sprintf("%x", h.Sum(nil))

	//
	// attempt to upload the release to S3
	fmt.Printf(stylish.Bullet("Uploading release to s3..."))

	v := url.Values{}
	v.Add("user_slug", api.UserSlug)
	v.Add("auth_token", api.AuthToken)
	v.Add("version", release.Version)

	//
	s3url, err := s3util.RequestURL(fmt.Sprintf("http://api.nanobox.io/v1/engines/%v/request_upload?%v", release.Name, v.Encode()))
	if err != nil {
		Config.Fatal("[commands/publish] s3.RequestURL() failed", err.Error())
	}

	//
	if err := s3util.Upload(s3url, archive); err != nil {
		Config.Fatal("[commands/publish] s3.Upload() failed", err.Error())
	}

	//
	// if the release uploaded successfully to s3, created one on odin
	fmt.Printf(stylish.Bullet("Uploading release to nanobox.io"))
	if _, err := api.CreateEngineRelease(release.Name, release); err != nil {
		fmt.Printf(stylish.ErrBullet("Unable to publish release (%v).", err))
		os.Exit(1)
	}
}
<commit_msg>Fix engine publish (#50) if directory exists<commit_after>//
package engine

import (
	"archive/tar"
	"bytes"
	"crypto/md5"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"time"

	api "github.com/nanobox-io/nanobox-api-client"
	"github.com/nanobox-io/nanobox-golang-stylish"
	"github.com/spf13/cobra"

	"github.com/nanobox-io/nanobox/config"
	engineutil "github.com/nanobox-io/nanobox/util/engine"
	fileutil "github.com/nanobox-io/nanobox/util/file"
	s3util "github.com/nanobox-io/nanobox/util/s3"
)

var tw *tar.Writer

//
var publishCmd = &cobra.Command{
	Use:   "publish",
	Short: "Publishes an engine to nanobox.io",
	Long:  ``,

	Run: publish,
}

// publish
func publish(ccmd *cobra.Command, args []string) {
	stylish.Header("publishing engine")

	//
	api.UserSlug, api.AuthToken = Auth.Authenticate()

	// create a new release
	fmt.Printf(stylish.Bullet("Creating release..."))
	release := &api.EngineRelease{}

	// create an annonymous struct to hold data that doesn't relate to a release but
	// is needed as part of the publish process
	opts := &struct {
		Generic  bool     `json:"generic"`
		Language string   `json:"language"`
		Overlays []string `json:"overlays"`
	}{}

	// ensure there is an Enginefile
	if _, err := os.Stat("./Enginefile"); err != nil {
		fmt.Printf("Enginefile not found. Be sure to publish from a project directory. Exiting...\n")
		os.Exit(1)
	}

	// parse the ./Enginefile into the new release
	if err := Config.ParseConfig("./Enginefile", release); err != nil {
		fmt.Printf("Nanobox failed to parse your Enginefile. Please ensure it is valid YAML and try again.\n")
		os.Exit(1)
	}

	// parse the ./Enginefile again to get the remaining fields
	if err := Config.ParseConfig("./Enginefile", opts); err != nil {
		fmt.Printf("Nanobox failed to parse your Enginefile. Please ensure it is valid YAML and try again.\n")
		os.Exit(1)
	}

	fmt.Printf(stylish.Bullet("Verifying engine is publishable..."))

	// determine if any required fields (name, version, language, summary) are missing,
	// if any are found to be missing exit 1
	// NOTE: I do this using fallthrough for asthetics onlye. The message is generic
	// enough that all cases will return the same message, and this looks better than
	// a single giant case (var == "" || var == "" || ...)
	switch {
	case opts.Language == "":
		fallthrough
	case release.Name == "":
		fallthrough
	case release.Summary == "":
		fallthrough
	case release.Version == "":
		fmt.Printf(stylish.Error("required fields missing", `Your Enginefile is missing one or more of the following required fields for publishing:

  name:      # the name of your project
  version:   # the current version of the project
  language:  # the lanauge (ruby, golang, etc.) of the engine
  summary:   # a 140 character summary of the project

Please ensure all required fields are provided and try again.`))

		os.Exit(1)
	}

	// attempt to read a README.md file and add it to the release...
	b, err := ioutil.ReadFile("./README.md")
	if err != nil {

		// this only fails if the file is not found, EOF is not an error. If no Readme
		// is found exit 1
		fmt.Printf(stylish.Error("missing readme", "Your engine is missing a README.md file. This file is required for publishing, as it is the only way for you to communicate how to use your engine. Please add a README.md and try again."))
		os.Exit(1)
	}

	//
	release.Readme = string(b)

	// check to see if the engine already exists on nanobox.io
	fmt.Printf(stylish.Bullet("Checking for existing engine on nanobox.io"))
	engine, err := api.GetEngine(api.UserSlug, release.Name)

	// if no engine exists, create a new one
	if err != nil {

		// if no engine is found create one
		if apiErr, _ := err.(api.APIError); apiErr.Code == 404 {

			fmt.Printf(stylish.SubTaskStart("Creating new engine on nanobox.io"))

			//
			engine = &api.Engine{
				Generic:      opts.Generic,
				LanguageName: opts.Language,
				Name:         release.Name,
			}

			//
			if _, err := api.CreateEngine(engine); err != nil {
				fmt.Printf(stylish.ErrBullet("Unable to create engine (%v).", err))
				os.Exit(1)
			}

			// wait until engine has been successfuly created before uploading to s3
			for {
				fmt.Print(".")

				p, err := api.GetEngine(api.UserSlug, release.Name)
				if err != nil {
					Config.Fatal("[commands/publish] api.GetEngine failed", err.Error())
				}

				// once the engine is "active", break
				if p.State == "active" {
					break
				}

				//
				time.Sleep(1000 * time.Millisecond)
			}

			// generically handle any other errors
		} else {
			Config.Fatal("[commands/publish] api.GetEngine failed", err.Error())
		}

		stylish.Success()
	}

	// create a meta.json file where we can add any extra data we might need; since
	// this is only used for internal purposes the file is removed once we're done
	// with it
	meta, err := os.Create("./meta.json")
	if err != nil {
		Config.Fatal("[commands/publish] os.Create() failed", err.Error())
	}
	defer meta.Close()
	defer os.Remove(meta.Name())

	// add any custom info to the metafile
	meta.WriteString(fmt.Sprintf(`{"engine_id": "%s"}`, engine.ID))

	// this is our predefined list of everything that gets archived as part of the
	// engine being published
	files := map[string][]string{
		"required": []string{"./bin", "./Enginefile", "./meta.json"},
		"optional": []string{"./lib", "./templates", "./files"},
	}

	// check to ensure no required files are missing
	for k, v := range files {
		if k == "required" {
			for _, f := range v {
				if _, err := os.Stat(f); err != nil {
					fmt.Printf(stylish.Error("required files missing", "Your Engine is missing one or more required files for publishing. Please read the following documentation to ensure all required files are included and try again.:\n\ndocs.nanobox.io/engines/project-creation/#example-engine-file-structure\n"))
					os.Exit(1)
				}
			}
		}
	}

	// create the temp engines folder for building the tarball
	tarPath := filepath.Join(config.EnginesDir, release.Name)
	if err := os.MkdirAll(tarPath, 0755); err != nil {
		Config.Fatal("[commands/engine/publish] os.Create() failed", err.Error())
	}

	// remove tarDir once published
	defer func() {
		if err := os.RemoveAll(tarPath); err != nil {
			os.Stderr.WriteString(stylish.ErrBullet("Failed to remove '%v'...", tarPath))
		}
	}()

	// parse the ./Enginefile again to get the overlays
	if err := Config.ParseConfig("./Enginefile", opts); err != nil {
		fmt.Printf("Nanobox failed to parse your Enginefile. Please ensure it is valid YAML and try again.\n")
		os.Exit(1)
	}

	// iterate through each overlay fetching it and untaring to the tar path
	for _, overlay := range opts.Overlays {
		engineutil.GetOverlay(overlay, tarPath)
	}

	// range over each file from each file type, building the final list of files
	// to be tarballed
	for _, v := range files {
		for _, f := range v {

			// not handling error here because an error simply means the file doesn't
			// exist and therefor wont be copied to the final tarball
			fileutil.Copy(f, tarPath)
		}
	}

	// create an empty buffer for writing the file contents to for the subsequent
	// upload
	archive := bytes.NewBuffer(nil)

	//
	h := md5.New()

	//
	if err := fileutil.Tar(tarPath, archive, h); err != nil {
		Config.Fatal("[commands/engine/publish] file.Tar() failed", err.Error())
	}

	// add the checksum for the new release once its finished being archived
	release.Checksum = fmt.Sprintf("%x", h.Sum(nil))

	//
	// attempt to upload the release to S3
	fmt.Printf(stylish.Bullet("Uploading release to s3..."))

	v := url.Values{}
	v.Add("user_slug", api.UserSlug)
	v.Add("auth_token", api.AuthToken)
	v.Add("version", release.Version)

	//
	s3url, err := s3util.RequestURL(fmt.Sprintf("http://api.nanobox.io/v1/engines/%v/request_upload?%v", release.Name, v.Encode()))
	if err != nil {
		Config.Fatal("[commands/publish] s3.RequestURL() failed", err.Error())
	}

	//
	if err := s3util.Upload(s3url, archive); err != nil {
		Config.Fatal("[commands/publish] s3.Upload() failed", err.Error())
	}

	//
	// if the release uploaded successfully to s3, created one on odin
	fmt.Printf(stylish.Bullet("Uploading release to nanobox.io"))
	if _, err := api.CreateEngineRelease(release.Name, release); err != nil {
		fmt.Printf(stylish.ErrBullet("Unable to publish release (%v).", err))
		os.Exit(1)
	}
}
<|endoftext|>


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

package commands

import "cocoon/db"

// GetBenchmarksCommand returns recent benchmark results.
type GetBenchmarksCommand struct {
}

// GetBenchmarksResult contains recent benchmark results.
type GetBenchmarksResult struct {
	Benchmarks []*BenchmarkData
}

// BenchmarkData contains benchmark data.
type BenchmarkData struct {
	Timeseries *db.TimeseriesEntity
	Values     []*db.TimeseriesValue
}

// GetBenchmarks returns recent benchmark results.
func GetBenchmarks(c *db.Cocoon, _ []byte) (interface{}, error) {
	seriesList, err := c.QueryTimeseries()

	if err != nil {
		return nil, err
	}

	var benchmarks []*BenchmarkData
	for _, series := range seriesList {
		values, _, err := c.QueryLatestTimeseriesValues(series, nil, 50)

		if err != nil {
			return nil, err
		}

		benchmarks = append(benchmarks, &BenchmarkData{
			Timeseries: series,
			Values:     values,
		})
	}

	return &GetBenchmarksResult{
		Benchmarks: benchmarks,
	}, nil
}
<commit_msg>memcache benchmarks (#153)<commit_after>// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package commands

import (
	"bytes"
	"cocoon/db"
	"compress/gzip"
	"encoding/json"
	"google.golang.org/appengine/memcache"
	"io"
	"time"
)

const cacheKey = "cached-get-benchmarks-result"

// GetBenchmarksCommand returns recent benchmark results.
type GetBenchmarksCommand struct {
}

// GetBenchmarksResult contains recent benchmark results.
type GetBenchmarksResult struct {
	Benchmarks []*BenchmarkData
}

// BenchmarkData contains benchmark data.
type BenchmarkData struct {
	Timeseries *db.TimeseriesEntity
	Values     []*db.TimeseriesValue
}

// GetBenchmarks returns recent benchmark results.
func GetBenchmarks(c *db.Cocoon, _ []byte) (interface{}, error) {
	cachedValue, err := loadFromMemcache(c)

	if err == nil {
		return cachedValue, nil
	} else if err == memcache.ErrCacheMiss {
		return loadFromDatabase(c)
	} else {
		return nil, err
	}
}

func loadFromMemcache(c *db.Cocoon) (*GetBenchmarksResult, error) {
	cachedValue, err := memcache.Get(c.Ctx, cacheKey)

	if err == nil {
		var result GetBenchmarksResult

		reader, err := gzip.NewReader(bytes.NewReader(cachedValue.Value))

		if err != nil {
			return nil, err
		}

		var decompressionBuffer bytes.Buffer
		io.Copy(&decompressionBuffer, reader)

		err = reader.Close()

		if err != nil {
			return nil, err
		}

		err = json.Unmarshal(decompressionBuffer.Bytes(), &result)

		if err != nil {
			return nil, err
		}

		return &result, nil
	} else {
		return nil, err
	}
}

func loadFromDatabase(c *db.Cocoon) (*GetBenchmarksResult, error) {
	seriesList, err := c.QueryTimeseries()

	if err != nil {
		return nil, err
	}

	var benchmarks []*BenchmarkData
	for _, series := range seriesList {
		values, _, err := c.QueryLatestTimeseriesValues(series, nil, 50)

		if err != nil {
			return nil, err
		}

		benchmarks = append(benchmarks, &BenchmarkData{
			Timeseries: series,
			Values:     values,
		})
	}

	result := &GetBenchmarksResult{
		Benchmarks: benchmarks,
	}

	err = storeInMemcache(c, result)

	if err != nil {
		return nil, err
	}

	return result, nil
}

func storeInMemcache(c *db.Cocoon, newValue *GetBenchmarksResult) error {
	jsonBytes, err := json.Marshal(newValue)

	if err != nil {
		return err
	}

	var compressionBuffer bytes.Buffer
	gzipWriter := gzip.NewWriter(&compressionBuffer)
	_, err = gzipWriter.Write(jsonBytes)

	if err != nil {
		return err
	}

	err = gzipWriter.Close()

	if err != nil {
		return err
	}

	const nanosInASecond = 1e9
	const twoMinutes = 120 * nanosInASecond

	err = memcache.Set(c.Ctx, &memcache.Item{
		Key:        cacheKey,
		Value:      compressionBuffer.Bytes(),
		Expiration: time.Duration(twoMinutes),
	})

	return err
}
<|endoftext|>


<commit_before>package plugins

import (
	"bytes"
	"fmt"
	"github.com/jovandeginste/medisana-bs/structs"
	"html/template"
	"log"
	"net/smtp"
	"sort"
	"strings"
	"time"
)

type Mail struct {
	Server        string
	SenderName    string
	SenderAddress string
	Recipients    map[int]structs.MailRecipient
	StartTLS      bool
	TemplateFile  string
	Subject       string
	Metrics       int
}

func (plugin Mail) Initialize() bool {
	log.Println("[PLUGIN MAIL] I am the Mail plugin")
	log.Printf("[PLUGIN MAIL]   - Server: %s\n", plugin.Server)
	log.Printf("[PLUGIN MAIL]   - StartTLS: %t\n", plugin.StartTLS)
	return true
}
func (plugin Mail) ParseData(person *structs.PersonMetrics) bool {
	log.Println("[PLUGIN MAIL] The mail plugin is parsing new data")
	plugin.sendMail(person)
	return true
}
func (mail Mail) sendMail(person *structs.PersonMetrics) {
	personId := person.Person
	recipient := mail.Recipients[personId]
	subject := mail.Subject

	metrics := make(structs.BodyMetrics, len(person.BodyMetrics))
	idx := 0
	for _, value := range person.BodyMetrics {
		metrics[idx] = value
		idx++
	}
	sort.Sort(metrics)
	lastMetrics := make(map[time.Time]structs.BodyMetric)
	for _, value := range metrics[len(metrics)-mail.Metrics:] {
		thetime := time.Unix(int64(value.Timestamp), 0)
		lastMetrics[thetime] = value
	}

	from := fmt.Sprintf("\"%s\" <%s>", mail.SenderName, mail.SenderAddress)
	to := recipient.Address

	var auth smtp.Auth
	auth = nil

	var msg string
	msg = msg + fmt.Sprintf("From: %s\r\n", from)
	msg = msg + fmt.Sprintf("To: %s\r\n", strings.Join(to, ";"))
	msg = msg + fmt.Sprintf("Subject: %s\r\n", subject)
	msg = msg + "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"

	msg = msg + "\r\n"
	parameters := struct {
		Name     string
		PersonId int
		Metrics  map[time.Time]structs.BodyMetric
	}{
		Name:     recipient.Name,
		PersonId: personId,
		Metrics:  lastMetrics,
	}
	body, err := ParseTemplate(mail.TemplateFile, parameters)
	if err != nil {
		log.Printf("[PLUGIN MAIL] An error occurred: %+v\n", err)
		return
	}
	msg = msg + body

	log.Printf("[PLUGIN MAIL] Sending mail to %s...\n", to)
	smtp.SendMail(mail.Server, auth, mail.SenderAddress, to, []byte(msg))
	log.Printf("[PLUGIN MAIL] Message was %d bytes.\n", len(msg))
}

func ParseTemplate(templateFileName string, data interface{}) (string, error) {
	var result string
	t, err := template.ParseFiles(templateFileName)

	if err != nil {
		return result, err
	}
	buf := new(bytes.Buffer)
	if err = t.Execute(buf, data); err != nil {
		return result, err
	}
	result = buf.String()
	return result, nil
}
<commit_msg>More logging for mail<commit_after>package plugins

import (
	"bytes"
	"fmt"
	"github.com/jovandeginste/medisana-bs/structs"
	"html/template"
	"log"
	"net/smtp"
	"sort"
	"strings"
	"time"
)

type Mail struct {
	Server        string
	SenderName    string
	SenderAddress string
	Recipients    map[int]structs.MailRecipient
	StartTLS      bool
	TemplateFile  string
	Subject       string
	Metrics       int
}

func (plugin Mail) Initialize() bool {
	log.Println("[PLUGIN MAIL] I am the Mail plugin")
	log.Printf("[PLUGIN MAIL]   - Server: %s\n", plugin.Server)
	log.Printf("[PLUGIN MAIL]   - StartTLS: %t [ To be implemented !!! ]\n", plugin.StartTLS)
	log.Printf("[PLUGIN MAIL]   - SenderName: %s\n", plugin.SenderName)
	log.Printf("[PLUGIN MAIL]   - SenderAddress: %s\n", plugin.SenderAddress)
	log.Printf("[PLUGIN MAIL]   - TemplateFile: %s\n", plugin.TemplateFile)
	log.Printf("[PLUGIN MAIL]   - Subject: %s\n", plugin.Subject)
	log.Printf("[PLUGIN MAIL]   - Metrics: %d\n", plugin.Metrics)
	return true
}
func (plugin Mail) ParseData(person *structs.PersonMetrics) bool {
	log.Println("[PLUGIN MAIL] The mail plugin is parsing new data")
	plugin.sendMail(person)
	return true
}
func (mail Mail) sendMail(person *structs.PersonMetrics) {
	personId := person.Person
	recipient := mail.Recipients[personId]
	subject := mail.Subject

	metrics := make(structs.BodyMetrics, len(person.BodyMetrics))
	idx := 0
	for _, value := range person.BodyMetrics {
		metrics[idx] = value
		idx++
	}
	sort.Sort(metrics)
	lastMetrics := make(map[time.Time]structs.BodyMetric)
	for _, value := range metrics[len(metrics)-mail.Metrics:] {
		thetime := time.Unix(int64(value.Timestamp), 0)
		lastMetrics[thetime] = value
	}

	from := fmt.Sprintf("\"%s\" <%s>", mail.SenderName, mail.SenderAddress)
	to := recipient.Address

	var auth smtp.Auth
	auth = nil

	var msg string
	msg = msg + fmt.Sprintf("From: %s\r\n", from)
	msg = msg + fmt.Sprintf("To: %s\r\n", strings.Join(to, ";"))
	msg = msg + fmt.Sprintf("Subject: %s\r\n", subject)
	msg = msg + "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"

	msg = msg + "\r\n"
	parameters := struct {
		Name     string
		PersonId int
		Metrics  map[time.Time]structs.BodyMetric
	}{
		Name:     recipient.Name,
		PersonId: personId,
		Metrics:  lastMetrics,
	}
	body, err := ParseTemplate(mail.TemplateFile, parameters)
	if err != nil {
		log.Printf("[PLUGIN MAIL] An error occurred: %+v\n", err)
		return
	}
	msg = msg + body

	log.Printf("[PLUGIN MAIL] Sending mail to %s...\n", to)
	smtp.SendMail(mail.Server, auth, mail.SenderAddress, to, []byte(msg))
	log.Printf("[PLUGIN MAIL] Message was %d bytes.\n", len(msg))
}

func ParseTemplate(templateFileName string, data interface{}) (string, error) {
	var result string
	t, err := template.ParseFiles(templateFileName)

	if err != nil {
		return result, err
	}
	buf := new(bytes.Buffer)
	if err = t.Execute(buf, data); err != nil {
		return result, err
	}
	result = buf.String()
	return result, nil
}
<|endoftext|>


<commit_before>package cove

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
)

func ExampleCoverageProfile() {
	testdir, _ := ioutil.TempDir("", "coverage-profile")
	defer os.RemoveAll(testdir)

	profile, _ := CoverageProfile(false, testdir, "text/scanner")
	fmt.Println(filepath.Base(profile))

	//Output:
	//text.scanner.out
}

func ExampleCoverageProfile_short() {
	testdir, _ := ioutil.TempDir("", "coverage-profile")
	defer os.RemoveAll(testdir)

	profile, _ := CoverageProfile(true, testdir, "text/scanner")
	fmt.Println(filepath.Base(profile))

	//Output:
	//text.scanner.out
}
func ExamplePackages_single() {

	packs, _ := Packages("text/template")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//text/template
}

func ExamplePackages_wildcard() {
	packs, _ := Packages("text/...")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExamplePackages_multiples() {
	packs, _ := Packages("text/...", "os/exec")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//os/exec
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExamplePackages_relative() {
	//duplicates are filtered
	packs, _ := Packages(".")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//github.com/MediaMath/cove
}

func ExamplePackages_unknown() {
	packs, err := Packages("foo/manchu", "text/...", "moo/...")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	if err != nil {
		fmt.Println("Had errors.")
	}

	//Output:
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
	//Had errors.
}

func ExamplePackages_unknown2() {
	packs, err := Packages("foo/manchu")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	if err != nil {
		fmt.Println("Had errors.")
	}

	//Output:
	//Had errors.
}

func ExamplePipeWith() {
	pipeWith(GoCmd("list", "os/exec", "text/..."), func(stdout io.Reader) error {
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			fmt.Println(scanner.Text())
		}

		return nil
	})

	//Output:
	//os/exec
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExampleOutputLines() {
	out, _ := output(GoCmd("list", "os/exec", "text/..."))

	for _, k := range out {
		fmt.Println(k)
	}

	//Output:
	//os/exec
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExamplePackageJSON() {
	var info struct {
		ImportPath string
		Name       string
		Incomplete bool
	}

	PackageJSON("os/exec", &info)

	fmt.Printf("%s %s %v", info.ImportPath, info.Name, info.Incomplete)

	//Output:
	//os/exec exec false
}

func ExamplePackageJSON_wildcard() {

	type JSONresponse struct {
		ImportPath string
		Name       string
		Incomplete bool
	}

	var resp []JSONresponse
	if err := PackageJSON("os/...", &resp); err != nil {
		fmt.Printf("'go list -json os/...' returns an invalid json in the multiple return case.")
	}

	//Output:
	//'go list -json os/...' returns an invalid json in the multiple return case.
}

func ExamplePackageJSON_unknown() {
	var info struct {
		ImportPath string
		Name       string
		Incomplete bool
	}

	if err := PackageJSON("moo/boo", &info); err != nil {
		fmt.Printf("'go list -json moo/boo' fails.")
	}

	//Output:
	//'go list -json moo/boo' fails.
}
<commit_msg>messing with jenkins<commit_after>package cove

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
)

func ExampleCoverageProfile() {
	testdir, _ := ioutil.TempDir("", "coverage-profile")
	defer os.RemoveAll(testdir)

	profile, _ := CoverageProfile(false, testdir, "text/scanner")
	fmt.Println(profile)

	//Output:
	//text.scanner.out
}

func ExampleCoverageProfile_short() {
	testdir, _ := ioutil.TempDir("", "coverage-profile")
	defer os.RemoveAll(testdir)

	profile, _ := CoverageProfile(true, testdir, "text/scanner")
	fmt.Println(filepath.Base(profile))

	//Output:
	//text.scanner.out
}
func ExamplePackages_single() {

	packs, _ := Packages("text/template")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//text/template
}

func ExamplePackages_wildcard() {
	packs, _ := Packages("text/...")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExamplePackages_multiples() {
	packs, _ := Packages("text/...", "os/exec")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//os/exec
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExamplePackages_relative() {
	//duplicates are filtered
	packs, _ := Packages(".")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	//Output:
	//github.com/MediaMath/cove
}

func ExamplePackages_unknown() {
	packs, err := Packages("foo/manchu", "text/...", "moo/...")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	if err != nil {
		fmt.Println("Had errors.")
	}

	//Output:
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
	//Had errors.
}

func ExamplePackages_unknown2() {
	packs, err := Packages("foo/manchu")

	for _, pack := range packs {
		fmt.Println(pack)
	}

	if err != nil {
		fmt.Println("Had errors.")
	}

	//Output:
	//Had errors.
}

func ExamplePipeWith() {
	pipeWith(GoCmd("list", "os/exec", "text/..."), func(stdout io.Reader) error {
		scanner := bufio.NewScanner(stdout)
		for scanner.Scan() {
			fmt.Println(scanner.Text())
		}

		return nil
	})

	//Output:
	//os/exec
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExampleOutputLines() {
	out, _ := output(GoCmd("list", "os/exec", "text/..."))

	for _, k := range out {
		fmt.Println(k)
	}

	//Output:
	//os/exec
	//text/scanner
	//text/tabwriter
	//text/template
	//text/template/parse
}

func ExamplePackageJSON() {
	var info struct {
		ImportPath string
		Name       string
		Incomplete bool
	}

	PackageJSON("os/exec", &info)

	fmt.Printf("%s %s %v", info.ImportPath, info.Name, info.Incomplete)

	//Output:
	//os/exec exec false
}

func ExamplePackageJSON_wildcard() {

	type JSONresponse struct {
		ImportPath string
		Name       string
		Incomplete bool
	}

	var resp []JSONresponse
	if err := PackageJSON("os/...", &resp); err != nil {
		fmt.Printf("'go list -json os/...' returns an invalid json in the multiple return case.")
	}

	//Output:
	//'go list -json os/...' returns an invalid json in the multiple return case.
}

func ExamplePackageJSON_unknown() {
	var info struct {
		ImportPath string
		Name       string
		Incomplete bool
	}

	if err := PackageJSON("moo/boo", &info); err != nil {
		fmt.Printf("'go list -json moo/boo' fails.")
	}

	//Output:
	//'go list -json moo/boo' fails.
}
<|endoftext|>


<commit_before>package config

import (
	"fmt"
	"os"

	"github.com/spf13/viper"
)

var (
	defaultBaseURL = "https://v2.exercism.io/api/v1"
)

// UserConfig contains user-specific settings.
type UserConfig struct {
	*Config
	Workspace  string
	Token      string
	Home       string
	APIBaseURL string
	settings   Configuration
}

// NewUserConfig loads a user configuration if it exists.
func NewUserConfig() (*UserConfig, error) {
	cfg := NewEmptyUserConfig()

	if err := cfg.Load(viper.New()); err != nil {
		return nil, err
	}

	return cfg, nil
}

// NewEmptyUserConfig creates a user configuration without loading it.
func NewEmptyUserConfig() *UserConfig {
	return &UserConfig{
		Config:   New(Dir(), "user"),
		settings: NewConfiguration(),
	}
}

// SetDefaults ensures that we have proper values where possible.
func (cfg *UserConfig) SetDefaults() {
	if cfg.Home == "" {
		cfg.Home = userHome()
	}
	if cfg.APIBaseURL == "" {
		cfg.APIBaseURL = defaultBaseURL
	}
	if cfg.Workspace == "" {
		dir := DefaultWorkspaceDir(cfg.settings)

		_, err := os.Stat(dir)
		// Sorry about the double negative.
		if !os.IsNotExist(err) {
			dir = fmt.Sprintf("%s-1", dir)
		}
		cfg.Workspace = dir
	}
}

// Write stores the config to disk.
func (cfg *UserConfig) Write() error {
	cfg.SetDefaults()
	return Write(cfg)
}

// Load reads a viper configuration into the config.
func (cfg *UserConfig) Load(v *viper.Viper) error {
	cfg.readIn(v)
	return v.Unmarshal(&cfg)
}
<commit_msg>Set default API base URL to api.exercism.io<commit_after>package config

import (
	"fmt"
	"os"

	"github.com/spf13/viper"
)

var (
	defaultBaseURL = "https://api.exercism.io/v1"
)

// UserConfig contains user-specific settings.
type UserConfig struct {
	*Config
	Workspace  string
	Token      string
	Home       string
	APIBaseURL string
	settings   Configuration
}

// NewUserConfig loads a user configuration if it exists.
func NewUserConfig() (*UserConfig, error) {
	cfg := NewEmptyUserConfig()

	if err := cfg.Load(viper.New()); err != nil {
		return nil, err
	}

	return cfg, nil
}

// NewEmptyUserConfig creates a user configuration without loading it.
func NewEmptyUserConfig() *UserConfig {
	return &UserConfig{
		Config:   New(Dir(), "user"),
		settings: NewConfiguration(),
	}
}

// SetDefaults ensures that we have proper values where possible.
func (cfg *UserConfig) SetDefaults() {
	if cfg.Home == "" {
		cfg.Home = userHome()
	}
	if cfg.APIBaseURL == "" {
		cfg.APIBaseURL = defaultBaseURL
	}
	if cfg.Workspace == "" {
		dir := DefaultWorkspaceDir(cfg.settings)

		_, err := os.Stat(dir)
		// Sorry about the double negative.
		if !os.IsNotExist(err) {
			dir = fmt.Sprintf("%s-1", dir)
		}
		cfg.Workspace = dir
	}
}

// Write stores the config to disk.
func (cfg *UserConfig) Write() error {
	cfg.SetDefaults()
	return Write(cfg)
}

// Load reads a viper configuration into the config.
func (cfg *UserConfig) Load(v *viper.Viper) error {
	cfg.readIn(v)
	return v.Unmarshal(&cfg)
}
<|endoftext|>


<commit_before>package command

import (
	"fmt"
	"strings"
)

// ReadCommand is a Command that reads data from the Vault.
type ReadCommand struct {
	Meta
}

func (c *ReadCommand) Run(args []string) int {
	var format string
	var field string
	flags := c.Meta.FlagSet("read", FlagSetDefault)
	flags.StringVar(&format, "format", "table", "")
	flags.StringVar(&field, "field", "", "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) != 1 {
		c.Ui.Error("read expects one argument")
		flags.Usage()
		return 1
	}

	path := args[0]
	if path[0] == '/' {
		path = path[1:]
	}

	client, err := c.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error initializing client: %s", err))
		return 2
	}

	secret, err := client.Logical().Read(path)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error reading %s: %s", path, err))
		return 1
	}
	if secret == nil {
		c.Ui.Error(fmt.Sprintf(
			"No value found at %s", path))
		return 1
	}

	// Handle single field output
	if field != "" {
		if val, ok := secret.Data[field]; ok {
			c.Ui.Output(val.(string))
			return 0
		} else {
			c.Ui.Error(fmt.Sprintf(
				"Field %s not present in secret", field))
			return 1
		}
	}

	return OutputSecret(c.Ui, format, secret)
}

func (c *ReadCommand) Synopsis() string {
	return "Read data or secrets from Vault"
}

func (c *ReadCommand) Help() string {
	helpText := `
Usage: vault read [options] path

  Read data from Vault.

  Read reads data at the given path from Vault. This can be used to
  read secrets and configuration as well as generate dynamic values from
  materialized backends. Please reference the documentation for the
  backends in use to determine key structure.

General Options:

  ` + generalOptionsUsage() + `

Read Options:

  -format=table           The format for output. By default it is a whitespace-
                          delimited table. This can also be json.

  -field=field            If included, the raw value of the specified field
  						  will be output raw to stdout.

`
	return strings.TrimSpace(helpText)
}
<commit_msg>CLI: Avoiding CR when printing specific fields<commit_after>package command

import (
	"fmt"
	"os"
	"strings"
)

// ReadCommand is a Command that reads data from the Vault.
type ReadCommand struct {
	Meta
}

func (c *ReadCommand) Run(args []string) int {
	var format string
	var field string
	flags := c.Meta.FlagSet("read", FlagSetDefault)
	flags.StringVar(&format, "format", "table", "")
	flags.StringVar(&field, "field", "", "")
	flags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := flags.Parse(args); err != nil {
		return 1
	}

	args = flags.Args()
	if len(args) != 1 {
		c.Ui.Error("read expects one argument")
		flags.Usage()
		return 1
	}

	path := args[0]
	if path[0] == '/' {
		path = path[1:]
	}

	client, err := c.Client()
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error initializing client: %s", err))
		return 2
	}

	secret, err := client.Logical().Read(path)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Error reading %s: %s", path, err))
		return 1
	}
	if secret == nil {
		c.Ui.Error(fmt.Sprintf(
			"No value found at %s", path))
		return 1
	}

	// Handle single field output
	if field != "" {
		if val, ok := secret.Data[field]; ok {
			// c.Ui.Output() prints a CR character which in this case is
			// not desired. Since Vault CLI currently only uses BasicUi,
			// which writes to standard output, os.Stdout is used here to
			// directly print the message. If mitchellh/cli exposes method
			// to print without CR, this has to be replaced by that.
			fmt.Fprintf(os.Stdout, val.(string))
			return 0
		} else {
			c.Ui.Error(fmt.Sprintf(
				"Field %s not present in secret", field))
			return 1
		}
	}

	return OutputSecret(c.Ui, format, secret)
}

func (c *ReadCommand) Synopsis() string {
	return "Read data or secrets from Vault"
}

func (c *ReadCommand) Help() string {
	helpText := `
Usage: vault read [options] path

  Read data from Vault.

  Read reads data at the given path from Vault. This can be used to
  read secrets and configuration as well as generate dynamic values from
  materialized backends. Please reference the documentation for the
  backends in use to determine key structure.

General Options:

  ` + generalOptionsUsage() + `

Read Options:

  -format=table           The format for output. By default it is a whitespace-
                          delimited table. This can also be json.

  -field=field            If included, the raw value of the specified field
  						  will be output raw to stdout.

`
	return strings.TrimSpace(helpText)
}
<|endoftext|>


<commit_before>package main

type JobStepStatus int

const (
	STARTING JobStepStatus = 1 + iota
	SUCCESS
	FAILURE
)

func (jss JobStepStatus) String() string {
	switch jss {
	case STARTING: return "STARTING"
	case SUCCESS: return "SUCCESS"
	case FAILURE: return "FAILURE"
	default: return "Unknown"
	}
}

type JobStep int

const (
	INITIALIZING JobStep = 1 + iota
	DOWNLOADING
	EXECUTING
	UPLOADING
	CLEANUP
	NACKSENDING
	CANCELLING
	ACKSENDING
)

var (
	JOB_STEP_DEFS = map[JobStep][]string {
		INITIALIZING: []string{"INITIALIZING"	, "info" , "error"},
		DOWNLOADING:	[]string{"DOWNLOADING", "info" , "error"},
		EXECUTING:		[]string{"EXECUTING"	,	"info" , "error"},
		UPLOADING:		[]string{"UPLOADING"	,	"info" , "error"},
		CLEANUP:			[]string{"CLEANUP"		, "info" , "warn" },
		NACKSENDING:	[]string{"NACKSENDING", "info" , "warn" },
		CANCELLING:		[]string{"CANCELLING" , "info" , "fatal"},
		ACKSENDING:		[]string{"ACKSENDING" , "info" , "fatal"},
	}
)

func (js JobStep) String() string {
	return JOB_STEP_DEFS[js][0]
}
func (js JobStep) successLogLevel() string {
	return JOB_STEP_DEFS[js][1]
}
func (js JobStep) failureLogLevel() string {
	return JOB_STEP_DEFS[js][2]
}

func (js JobStep) completed(st JobStepStatus) bool {
	return (js == ACKSENDING) && (st == SUCCESS)
}
func (js JobStep) logLevelFor(st JobStepStatus) string {
	switch st {
	// case STARTING: return "info"
	case SUCCESS: return js.successLogLevel()
	case FAILURE: return js.failureLogLevel()
	default: return "info"
	}
}
<commit_msg>:recycle: Remove log level on SUCCESS from JOB_STEP_DEFS<commit_after>package main

type JobStepStatus int

const (
	STARTING JobStepStatus = 1 + iota
	SUCCESS
	FAILURE
)

func (jss JobStepStatus) String() string {
	switch jss {
	case STARTING: return "STARTING"
	case SUCCESS: return "SUCCESS"
	case FAILURE: return "FAILURE"
	default: return "Unknown"
	}
}

type JobStep int

const (
	INITIALIZING JobStep = 1 + iota
	DOWNLOADING
	EXECUTING
	UPLOADING
	CLEANUP
	NACKSENDING
	CANCELLING
	ACKSENDING
)

var (
	JOB_STEP_DEFS = map[JobStep][]string {
		INITIALIZING: []string{"INITIALIZING"	, "error"},
		DOWNLOADING:	[]string{"DOWNLOADING", "error"},
		EXECUTING:		[]string{"EXECUTING"	,	"error"},
		UPLOADING:		[]string{"UPLOADING"	,	"error"},
		CLEANUP:			[]string{"CLEANUP"		, "warn" },
		NACKSENDING:	[]string{"NACKSENDING", "warn" },
		CANCELLING:		[]string{"CANCELLING" , "fatal"},
		ACKSENDING:		[]string{"ACKSENDING" , "fatal"},
	}
)

func (js JobStep) String() string {
	return JOB_STEP_DEFS[js][0]
}
func (js JobStep) failureLogLevel() string {
	return JOB_STEP_DEFS[js][1]
}

func (js JobStep) completed(st JobStepStatus) bool {
	return (js == ACKSENDING) && (st == SUCCESS)
}
func (js JobStep) logLevelFor(st JobStepStatus) string {
	switch st {
	// case STARTING: return "info"
	case SUCCESS: return js.successLogLevel()
	case FAILURE: return js.failureLogLevel()
	default: return "info"
	}
}
<|endoftext|>


<commit_before>package gonavitia

import (
	"fmt"
	"github.com/aabizri/gonavitia/types"
	"net/url"
	"strconv"
	"time"
)

// JourneyResults countains the results of a Journey request
type JourneyResults struct {
	Journeys []types.Journey

	Logging

	session *Session
}

// String satisfies stringer, pretty-prints JourneyResults
func (jr JourneyResults) String() string {
	var msg string
	for i, journey := range jr.Journeys {
		if i != 0 {
			msg += "\n"
		}
		msg += fmt.Sprintf("Journey #%d: %s\n", i, journey.String())
	}
	return msg
}

// JourneyRequest countain the parameters needed to make a Journey request
type JourneyRequest struct {
	// There must be at least one From or To parameter defined
	// When used with just one of them, the resulting Journey won't have a populated Sections field.
	From types.QueryEscaper
	To   types.QueryEscaper

	Date          time.Time
	DateIsArrival bool

	// The traveler's type
	Traveler types.TravelerType

	// Define the freshness of data to use to compute journeys
	Freshness types.DataFreshness

	// Forbidden public transport objects
	Forbidden []types.ID

	// Allowed public transport objects
	// Note: This counstraint intersects with Forbidden
	Allowed []types.ID

	// Force the first section mode if it isn't a public transport mode
	// Note: The parameter is inclusive, not exclusive. As such if you want to forbid a mode you have to include all modes except that one.
	FirstSectionModes []types.Mode

	// Same, but for the last section
	LastSectionModes []types.Mode

	// MaxDurationToPT is the maximum allowed duration to reach the public transport.
	// Use this to limit the walking/biking part.
	MaxDurationToPT time.Duration

	// These four following parameters set the speed of each mode (Walking, Bike, BSS & car)
	// In meters per second
	WalkingSpeed   float64
	BikeSpeed      float64
	BikeShareSpeed float64
	CarSpeed       float64

	// Minimum and maximum amounts of journeys suggested
	MinJourneys uint
	MaxJourneys uint

	// Count fixes the amount of journeys to be returned, overriding minimum & maximum amount
	// Note: if Count=0 then it isn't taken into account
	Count uint

	// Maximum number of transfers in each journey
	MaxTransfers uint

	// Maximum duration of a trip
	MaxDuration time.Duration // To seconds

	// Wheelchair restricts the answer to accessible public transports
	Wheelchair bool
}

// toURL formats a journey request to url
// Should be refactored using a switch statement
func (req JourneyRequest) toURL() (url.Values, error) {
	params := url.Values{}

	// Define a few useful functions
	addUint := func(key string, amount uint64) {
		if amount != 0 {
			str := strconv.FormatUint(amount, 10)
			params.Add(key, str)
		}
	}
	addInt := func(key string, amount int64) {
		if amount != 0 {
			str := strconv.FormatInt(amount, 10)
			params.Add(key, str)
		}
	}
	addString := func(key string, str string) {
		if str != "" {
			params.Add(key, str)
		}
	}
	addIDSlice := func(key string, ids []types.ID) {
		if len(ids) != 0 {
			for _, id := range ids {
				params.Add(key, id.QueryEscape())
			}
		}
	}
	addModes := func(key string, modes []types.Mode) {
		if len(modes) != 0 {
			for _, mode := range modes {
				params.Add(key, string(mode))
			}
		}
	}
	addFloat := func(key string, amount float64) {
		if amount != 0 {
			speedStr := strconv.FormatFloat(amount, 'f', 3, 64)
			params.Add(key, speedStr)
		}
	}

	// Encode the from and to
	if from := req.From; from != nil {
		params.Add("from", from.QueryEscape())
	}
	if to := req.To; to != nil {
		params.Add("to", to.QueryEscape())
	}

	if datetime := req.Date; !datetime.IsZero() {
		str := datetime.Format(types.DateTimeFormat)
		params.Add("datetime", str)
		if req.DateIsArrival {
			params.Add("datetime_represents", "arrival")
		}
	}

	addString("traveler_type", string(req.Traveler))

	addString("data_freshness", string(req.Freshness))

	addIDSlice("forbidden_uris[]", req.Forbidden)

	addIDSlice("allowed_id[]", req.Allowed)

	addModes("first_section_mode[]", req.FirstSectionModes)

	addModes("last_section_mode[]", req.LastSectionModes)

	// max_duration_to_pt
	addInt("max_duration_to_pt", int64(req.MaxDurationToPT/time.Second))

	// walking_speed, bike_speed, bss_speed & car_speed
	addFloat("walking_speed", req.WalkingSpeed)
	addFloat("bike_speed", req.BikeSpeed)
	addFloat("bss_speed", req.BikeShareSpeed)
	addFloat("car_speed", req.CarSpeed)

	// If count is defined don't bother with the minimimal and maximum amount of items to return
	if count := req.Count; count != 0 {
		addUint("count", uint64(count))
	} else {
		addUint("min_nb_journeys", uint64(req.MinJourneys))
		addUint("max_nb_journeys", uint64(req.MaxJourneys))
	}

	// max_nb_transfers
	addUint("max_nb_transfers", uint64(req.MaxTransfers))

	// max_duration
	addInt("max_duration", int64(req.MaxDuration/time.Second))

	// wheelchair
	if req.Wheelchair {
		params.Add("wheelchair", "true")
	}

	return params, nil
}

// journeys is the internal function used by Journeys functions
func (s *Session) journeys(url string, params JourneyRequest) (*JourneyResults, error) {
	var results = &JourneyResults{session: s}
	err := s.request(url, params, results)
	return results, err
}

const journeysEndpoint string = "journeys"

// Journeys computes a list of journeys according to the parameters given
func (s *Session) Journeys(params JourneyRequest) (*JourneyResults, error) {
	// Create the URL
	url := s.APIURL + "/" + journeysEndpoint

	// Call
	return s.journeys(url, params)
}

// JourneysR computes a list of journeys according to the parameters given and in a specific region
func (s *Session) JourneysR(params JourneyRequest, regionID string) (*JourneyResults, error) {
	// Create the URL
	url := s.APIURL + "/coverage/" + regionID + "/" + journeysEndpoint

	// Call
	return s.journeys(url, params)
}
<commit_msg>Add more info for JourneyRequest<commit_after>package gonavitia

import (
	"fmt"
	"github.com/aabizri/gonavitia/types"
	"net/url"
	"strconv"
	"time"
)

// JourneyResults countains the results of a Journey request
type JourneyResults struct {
	Journeys []types.Journey

	Logging

	session *Session
}

// String satisfies stringer, pretty-prints JourneyResults
func (jr JourneyResults) String() string {
	var msg string
	for i, journey := range jr.Journeys {
		if i != 0 {
			msg += "\n"
		}
		msg += fmt.Sprintf("Journey #%d: %s\n", i, journey.String())
	}
	return msg
}

// JourneyRequest countain the parameters needed to make a Journey request
type JourneyRequest struct {
	// There must be at least one From or To parameter defined
	// When used with just one of them, the resulting Journey won't have a populated Sections field.
	From types.QueryEscaper
	To   types.QueryEscaper

	// When do you want to depart ? Or is DateIsArrival when do you want to arrive at your destination.
	Date          time.Time
	DateIsArrival bool

	// The traveler's type
	Traveler types.TravelerType

	// Define the freshness of data to use to compute journeys
	Freshness types.DataFreshness

	// Forbidden public transport objects
	Forbidden []types.ID

	// Allowed public transport objects
	// Note: This counstraint intersects with Forbidden
	Allowed []types.ID

	// Force the first section mode if it isn't a public transport mode
	// Note: The parameter is inclusive, not exclusive. As such if you want to forbid a mode you have to include all modes except that one.
	FirstSectionModes []types.Mode

	// Same, but for the last section
	LastSectionModes []types.Mode

	// MaxDurationToPT is the maximum allowed duration to reach the public transport.
	// Use this to limit the walking/biking part.
	MaxDurationToPT time.Duration

	// These four following parameters set the speed of each mode (Walking, Bike, BSS & car)
	// In meters per second
	WalkingSpeed   float64
	BikeSpeed      float64
	BikeShareSpeed float64
	CarSpeed       float64

	// Minimum and maximum amounts of journeys suggested
	MinJourneys uint
	MaxJourneys uint

	// Count fixes the amount of journeys to be returned, overriding minimum & maximum amount
	// Note: if Count=0 then it isn't taken into account
	Count uint

	// Maximum number of transfers in each journey
	MaxTransfers uint

	// Maximum duration of a trip
	MaxDuration time.Duration // To seconds

	// Wheelchair restricts the answer to accessible public transports
	Wheelchair bool
}

// toURL formats a journey request to url
// Should be refactored using a switch statement
func (req JourneyRequest) toURL() (url.Values, error) {
	params := url.Values{}

	// Define a few useful functions
	addUint := func(key string, amount uint64) {
		if amount != 0 {
			str := strconv.FormatUint(amount, 10)
			params.Add(key, str)
		}
	}
	addInt := func(key string, amount int64) {
		if amount != 0 {
			str := strconv.FormatInt(amount, 10)
			params.Add(key, str)
		}
	}
	addString := func(key string, str string) {
		if str != "" {
			params.Add(key, str)
		}
	}
	addIDSlice := func(key string, ids []types.ID) {
		if len(ids) != 0 {
			for _, id := range ids {
				params.Add(key, id.QueryEscape())
			}
		}
	}
	addModes := func(key string, modes []types.Mode) {
		if len(modes) != 0 {
			for _, mode := range modes {
				params.Add(key, string(mode))
			}
		}
	}
	addFloat := func(key string, amount float64) {
		if amount != 0 {
			speedStr := strconv.FormatFloat(amount, 'f', 3, 64)
			params.Add(key, speedStr)
		}
	}

	// Encode the from and to
	if from := req.From; from != nil {
		params.Add("from", from.QueryEscape())
	}
	if to := req.To; to != nil {
		params.Add("to", to.QueryEscape())
	}

	if datetime := req.Date; !datetime.IsZero() {
		str := datetime.Format(types.DateTimeFormat)
		params.Add("datetime", str)
		if req.DateIsArrival {
			params.Add("datetime_represents", "arrival")
		}
	}

	addString("traveler_type", string(req.Traveler))

	addString("data_freshness", string(req.Freshness))

	addIDSlice("forbidden_uris[]", req.Forbidden)

	addIDSlice("allowed_id[]", req.Allowed)

	addModes("first_section_mode[]", req.FirstSectionModes)

	addModes("last_section_mode[]", req.LastSectionModes)

	// max_duration_to_pt
	addInt("max_duration_to_pt", int64(req.MaxDurationToPT/time.Second))

	// walking_speed, bike_speed, bss_speed & car_speed
	addFloat("walking_speed", req.WalkingSpeed)
	addFloat("bike_speed", req.BikeSpeed)
	addFloat("bss_speed", req.BikeShareSpeed)
	addFloat("car_speed", req.CarSpeed)

	// If count is defined don't bother with the minimimal and maximum amount of items to return
	if count := req.Count; count != 0 {
		addUint("count", uint64(count))
	} else {
		addUint("min_nb_journeys", uint64(req.MinJourneys))
		addUint("max_nb_journeys", uint64(req.MaxJourneys))
	}

	// max_nb_transfers
	addUint("max_nb_transfers", uint64(req.MaxTransfers))

	// max_duration
	addInt("max_duration", int64(req.MaxDuration/time.Second))

	// wheelchair
	if req.Wheelchair {
		params.Add("wheelchair", "true")
	}

	return params, nil
}

// journeys is the internal function used by Journeys functions
func (s *Session) journeys(url string, params JourneyRequest) (*JourneyResults, error) {
	var results = &JourneyResults{session: s}
	err := s.request(url, params, results)
	return results, err
}

const journeysEndpoint string = "journeys"

// Journeys computes a list of journeys according to the parameters given
func (s *Session) Journeys(params JourneyRequest) (*JourneyResults, error) {
	// Create the URL
	url := s.APIURL + "/" + journeysEndpoint

	// Call
	return s.journeys(url, params)
}

// JourneysR computes a list of journeys according to the parameters given and in a specific region
func (s *Session) JourneysR(params JourneyRequest, regionID string) (*JourneyResults, error) {
	// Create the URL
	url := s.APIURL + "/coverage/" + regionID + "/" + journeysEndpoint

	// Call
	return s.journeys(url, params)
}
<|endoftext|>