<commit_before>package main

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"os"
	"regexp"
	"text/template"
)

type Command func(*Changelog, []string)

type Release struct {
	Version    string
	Date       string
	Summary    string
	Added      []string
	Changed    []string
	Deprecated []string
	Removed    []string
	Fixed      []string
	Security   []string
}

type Changelog []Release

var REGEXP_FILENAME = regexp.MustCompile(`^(?i)change(-|_)?log(.yml|.yaml)?$`)
var DEFAULT_COMMAND = "release"
var COMMAND_MAPPING = map[string]Command{
	"release": release,
	"to":      to,
}
var ERROR_READING = 1
var ERROR_PARSING = 2
var ERROR_RELEASE = 3
var ERROR_TO = 4
var REGEXP_DATE = regexp.MustCompile(`^\d\d\d\d-\d\d-\d\d$`)
var REGEXP_VERSION = regexp.MustCompile(`^\d+(\.\d+)?(\.\d+)?$`)
var HTML_TEMPLATE = `<!DOCTYPE html>

<title>Change Log</title>
<meta charset="utf-8">
{{ range $stylesheet := .Stylesheets }}

{{ end }}

Change Log

{{ range $release := .Changelog }}

Release {{ .Version }} ({{ .Date }})

{{ .Summary }}

{{ if .Added }}

Added

{{ range $entry := .Added }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Changed }}

Changed

{{ range $entry := .Changed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Deprecated }}

Deprecated

{{ range $entry := .Deprecated }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Removed }}

Removed

{{ range $entry := .Removed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Fixed }}

Fixed

{{ range $entry := .Fixed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Security }}

Security

{{ range $entry := .Security }}

{{ . }}

{{ end }}

{{ end }}
{{ end }}

`

func Error(code int, message string) {
	fmt.Fprintln(os.Stderr, message)
	os.Exit(code)
}

func Errorf(code int, message string, args ...interface{}) {
	Error(code, fmt.Sprintf(message, args...))
}

func readChangelog() []byte {
	files, err := ioutil.ReadDir(".")
	if err != nil {
		Error(ERROR_READING, "Could not list current directory")
	}
	for _, file := range files {
		if !file.IsDir() && REGEXP_FILENAME.MatchString(file.Name()) {
			source, err := ioutil.ReadFile(file.Name())
			if err != nil {
				Errorf(ERROR_READING, "Error reading changelog file '%s'\n", file.Name())
			}
			return source
		}
	}
	Error(ERROR_READING, "No changelog file found")
	return []byte{}
}

func parseChangelog(source []byte) *Changelog {
	var changelog Changelog
	err := yaml.Unmarshal(source, &changelog)
	if err != nil {
		Errorf(ERROR_PARSING, "Error parsing changelog: %s\n", err.Error())
	}
	return &changelog
}

////////////////////////////////////////////////////////////////////////////////
//                                  COMMANDS                                  //
////////////////////////////////////////////////////////////////////////////////

func checkRelease(release Release) {
	if release.Version == "" {
		Error(ERROR_RELEASE, "Release version is empty")
	}
	if !REGEXP_VERSION.MatchString(release.Version) {
		Errorf(ERROR_RELEASE, "Release version '%s' is not a valid semantic version number", release.Version)
	}
	if release.Date == "" {
		Error(ERROR_RELEASE, "Release date is empty")
	}
	if !REGEXP_DATE.MatchString(release.Date) {
		Errorf(ERROR_RELEASE, "Release date '%s' is not valid ISO format", release.Date)
	}
	if release.Summary == "" {
		Error(ERROR_RELEASE, "Release summary is empty")
	}
}

func checkChangelog(changelog *Changelog) {
	if len(*changelog) == 0 {
		Error(ERROR_RELEASE, "Release is empy")
	}
	for _, release := range *changelog {
		checkRelease(release)
	}
}

func release(changelog *Changelog, args []string) {
	checkChangelog(changelog)
	if len(args) > 0 {
		if args[0] == "summary" {
			fmt.Println((*changelog)[0].Summary)
		} else if args[0] == "date" {
			fmt.Println((*changelog)[0].Date)
		} else if args[0] == "version" {
			fmt.Println((*changelog)[0].Version)
		} else {
			Errorf(ERROR_RELEASE, "Unknown release argument %s", args[0])
		}
	}
}

type HtmlTemplateData struct {
	Changelog   *Changelog
	Stylesheets []string
}

func toHtml(changelog *Changelog, args []string) {
	stylesheets := make([]string, 0)
	for _, file := range args {
		stylesheet, err := ioutil.ReadFile(file)
		if err != nil {
			Errorf(ERROR_TO, "Error loading stylesheet %s: %s", file, err.Error())
		}
		stylesheets = append(stylesheets, string(stylesheet))
	}
	data := HtmlTemplateData{
		Stylesheets: stylesheets,
		Changelog:   changelog,
	}
	t := template.Must(template.New("changelog").Parse(HTML_TEMPLATE))
	err := t.Execute(os.Stdout, data)
	if err != nil {
		Errorf(ERROR_TO, "Error processing template: %s", err)
	}
}

func to(changelog *Changelog, args []string) {
	checkChangelog(changelog)
	if len(args) < 1 {
		Error(ERROR_TO, "You must pass format to convert to")
	}
	format := args[0]
	if format != "html" {
		Errorf(ERROR_TO, "Unknown format %s", args[0])
	}
	toHtml(changelog, args[1:])
}

func main() {
	changelog := parseChangelog(readChangelog())
	var command string
	var args []string
	if len(os.Args) < 2 {
		command = DEFAULT_COMMAND
		args = []string(nil)
	} else {
		command = os.Args[1]
		args = os.Args[2:]
	}
	function := COMMAND_MAPPING[command]
	if function != nil {
		function(changelog, args)
	} else {
		fmt.Printf("Command %s unknown\n", command)
		os.Exit(3)
	}
}
<commit_msg>Reading changelog from stdin if available<commit_after>package main

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"io/ioutil"
	"os"
	"regexp"
	"text/template"
)

type Command func(*Changelog, []string)

type Release struct {
	Version    string
	Date       string
	Summary    string
	Added      []string
	Changed    []string
	Deprecated []string
	Removed    []string
	Fixed      []string
	Security   []string
}

type Changelog []Release

var REGEXP_FILENAME = regexp.MustCompile(`^(?i)change(-|_)?log(.yml|.yaml)?$`)
var DEFAULT_COMMAND = "release"
var COMMAND_MAPPING = map[string]Command{
	"release": release,
	"to":      to,
}
var ERROR_READING = 1
var ERROR_PARSING = 2
var ERROR_RELEASE = 3
var ERROR_TO = 4
var REGEXP_DATE = regexp.MustCompile(`^\d\d\d\d-\d\d-\d\d$`)
var REGEXP_VERSION = regexp.MustCompile(`^\d+(\.\d+)?(\.\d+)?$`)
var HTML_TEMPLATE = `<!DOCTYPE html>

<title>Change Log</title>
<meta charset="utf-8">
{{ range $stylesheet := .Stylesheets }}

{{ end }}

Change Log

{{ range $release := .Changelog }}

Release {{ .Version }} ({{ .Date }})

{{ .Summary }}

{{ if .Added }}

Added

{{ range $entry := .Added }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Changed }}

Changed

{{ range $entry := .Changed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Deprecated }}

Deprecated

{{ range $entry := .Deprecated }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Removed }}

Removed

{{ range $entry := .Removed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Fixed }}

Fixed

{{ range $entry := .Fixed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Security }}

Security

{{ range $entry := .Security }}

{{ . }}

{{ end }}

{{ end }}
{{ end }}

`

func Error(code int, message string) {
	fmt.Fprintln(os.Stderr, message)
	os.Exit(code)
}

func Errorf(code int, message string, args ...interface{}) {
	Error(code, fmt.Sprintf(message, args...))
}

func readChangelog() []byte {
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) == 0 {
		// data is being piped to stdin
		source, err := ioutil.ReadAll(os.Stdin)
		if err != nil {
			Error(ERROR_READING, "Error reading changelog from stdin")
		}
		return source
	} else {
		// look for changelog in current directory
		files, err := ioutil.ReadDir(".")
		if err != nil {
			Error(ERROR_READING, "Could not list current directory")
		}
		for _, file := range files {
			if !file.IsDir() && REGEXP_FILENAME.MatchString(file.Name()) {
				source, err := ioutil.ReadFile(file.Name())
				if err != nil {
					Errorf(ERROR_READING, "Error reading changelog file '%s'\n", file.Name())
				}
				return source
			}
		}
		Error(ERROR_READING, "No changelog file found")
		return []byte{}
	}
}

func parseChangelog(source []byte) *Changelog {
	var changelog Changelog
	err := yaml.Unmarshal(source, &changelog)
	if err != nil {
		Errorf(ERROR_PARSING, "Error parsing changelog: %s\n", err.Error())
	}
	return &changelog
}

////////////////////////////////////////////////////////////////////////////////
//                                  COMMANDS                                  //
////////////////////////////////////////////////////////////////////////////////

func checkRelease(release Release) {
	if release.Version == "" {
		Error(ERROR_RELEASE, "Release version is empty")
	}
	if !REGEXP_VERSION.MatchString(release.Version) {
		Errorf(ERROR_RELEASE, "Release version '%s' is not a valid semantic version number", release.Version)
	}
	if release.Date == "" {
		Error(ERROR_RELEASE, "Release date is empty")
	}
	if !REGEXP_DATE.MatchString(release.Date) {
		Errorf(ERROR_RELEASE, "Release date '%s' is not valid ISO format", release.Date)
	}
	if release.Summary == "" {
		Error(ERROR_RELEASE, "Release summary is empty")
	}
}

func checkChangelog(changelog *Changelog) {
	if len(*changelog) == 0 {
		Error(ERROR_RELEASE, "Release is empy")
	}
	for _, release := range *changelog {
		checkRelease(release)
	}
}

func release(changelog *Changelog, args []string) {
	checkChangelog(changelog)
	if len(args) > 0 {
		if args[0] == "summary" {
			fmt.Println((*changelog)[0].Summary)
		} else if args[0] == "date" {
			fmt.Println((*changelog)[0].Date)
		} else if args[0] == "version" {
			fmt.Println((*changelog)[0].Version)
		} else {
			Errorf(ERROR_RELEASE, "Unknown release argument %s", args[0])
		}
	}
}

type HtmlTemplateData struct {
	Changelog   *Changelog
	Stylesheets []string
}

func toHtml(changelog *Changelog, args []string) {
	stylesheets := make([]string, 0)
	for _, file := range args {
		stylesheet, err := ioutil.ReadFile(file)
		if err != nil {
			Errorf(ERROR_TO, "Error loading stylesheet %s: %s", file, err.Error())
		}
		stylesheets = append(stylesheets, string(stylesheet))
	}
	data := HtmlTemplateData{
		Stylesheets: stylesheets,
		Changelog:   changelog,
	}
	t := template.Must(template.New("changelog").Parse(HTML_TEMPLATE))
	err := t.Execute(os.Stdout, data)
	if err != nil {
		Errorf(ERROR_TO, "Error processing template: %s", err)
	}
}

func to(changelog *Changelog, args []string) {
	checkChangelog(changelog)
	if len(args) < 1 {
		Error(ERROR_TO, "You must pass format to convert to")
	}
	format := args[0]
	if format != "html" {
		Errorf(ERROR_TO, "Unknown format %s", args[0])
	}
	toHtml(changelog, args[1:])
}

func main() {
	changelog := parseChangelog(readChangelog())
	var command string
	var args []string
	if len(os.Args) < 2 {
		command = DEFAULT_COMMAND
		args = []string(nil)
	} else {
		command = os.Args[1]
		args = os.Args[2:]
	}
	function := COMMAND_MAPPING[command]
	if function != nil {
		function(changelog, args)
	} else {
		fmt.Printf("Command %s unknown\n", command)
		os.Exit(3)
	}
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
    "time"
    "github.com/boombuler/led"
    "image/color"
    "math/rand"
    "os"
    "sort"
    "strings"
    "regexp"
    "encoding/hex"
    "gopkg.in/alecthomas/kingpin.v1"
)

var (
    VERSION = "0.0.1"
    flagSetColor = kingpin.Flag("set-color", "Set color for device. The format must be \"#rrggbb\" or \"random\" or an HTML color name, like \"green\"").String()
    flagListColors = kingpin.Flag("list-colors", "List all available HTML color names").Bool()
)

func printListColorNames() {
    var colorNames []string
    for k := range colors {
        colorNames = append(colorNames, k)
    }
    sort.Strings(colorNames)
    for k := range colorNames {
        if (k > 0) {
            fmt.Print(",")
        }
        fmt.Print(colorNames[k])
    }
}

func getFlagColor() color.Color {
    *flagSetColor = strings.ToLower(*flagSetColor)
    if (*flagSetColor == "random") {
        rand.Seed(time.Now().UnixNano())
        return color.RGBA{uint8(rand.Int()), uint8(rand.Int()), uint8(rand.Int()), 0xFF}
    }
    if (colors[*flagSetColor] != nil) {
        return colors[*flagSetColor]
    }
    validHexCode := regexp.MustCompile(`^#?([a-f0-9]{6})$`)
    if (validHexCode.MatchString(*flagSetColor)) {
        hexStr := validHexCode.FindStringSubmatch(*flagSetColor)
        bytes, err := hex.DecodeString(hexStr[1])
        if (err != nil) {
            fmt.Printf("invalid color code '%s'. use '#rrggbb' instead", hexStr[1])
            return nil
        }
        return color.RGBA{uint8(bytes[0]), uint8(bytes[1]), uint8(bytes[2]), 0xFF}
    }
    return nil
}

func main() {

    kingpin.Version(VERSION)
    kingpin.Parse()

    if (len(os.Args) <= 1) {
        kingpin.Usage()
        os.Exit(0)
    }

    if (flagListColors != nil && *flagListColors) {
        printListColorNames()
        os.Exit(0)
    }

    if (flagSetColor == nil) {
        os.Exit(0)
    }

    for devInfo := range led.Devices() {
        dev, err := devInfo.Open()
        if err != nil {
            fmt.Println(err)
            continue
        }
        defer dev.Close()

        col := getFlagColor()
        if (col != nil) {
            dev.SetColor(col)
            time.Sleep(2 * time.Second)
        }

    }

}
<commit_msg>don't set BLACK color when exit the program<commit_after>package main

import (
    "fmt"
    "time"
    "github.com/nitram509/led"
    "image/color"
    "math/rand"
    "os"
    "sort"
    "strings"
    "regexp"
    "encoding/hex"
    "gopkg.in/alecthomas/kingpin.v1"
)

var (
    VERSION = "0.0.1"
    flagSetColor = kingpin.Flag("set-color", "Set color for device. The format must be \"#rrggbb\" or \"random\" or an HTML color name, like \"green\"").String()
    flagListColors = kingpin.Flag("list-colors", "List all available HTML color names").Bool()
)

func printListColorNames() {
    var colorNames []string
    for k := range colors {
        colorNames = append(colorNames, k)
    }
    sort.Strings(colorNames)
    for k := range colorNames {
        if (k > 0) {
            fmt.Print(",")
        }
        fmt.Print(colorNames[k])
    }
}

func getFlagColor() color.Color {
    *flagSetColor = strings.ToLower(*flagSetColor)
    if (*flagSetColor == "random") {
        rand.Seed(time.Now().UnixNano())
        return color.RGBA{uint8(rand.Int()), uint8(rand.Int()), uint8(rand.Int()), 0xFF}
    }
    if (colors[*flagSetColor] != nil) {
        return colors[*flagSetColor]
    }
    validHexCode := regexp.MustCompile(`^#?([a-f0-9]{6})$`)
    if (validHexCode.MatchString(*flagSetColor)) {
        hexStr := validHexCode.FindStringSubmatch(*flagSetColor)
        bytes, err := hex.DecodeString(hexStr[1])
        if (err != nil) {
            fmt.Printf("invalid color code '%s'. use '#rrggbb' instead", hexStr[1])
            return nil
        }
        return color.RGBA{uint8(bytes[0]), uint8(bytes[1]), uint8(bytes[2]), 0xFF}
    }
    return nil
}

func main() {

    kingpin.Version(VERSION)
    kingpin.Parse()

    if (len(os.Args) <= 1) {
        kingpin.Usage()
        os.Exit(0)
    }

    if (flagListColors != nil && *flagListColors) {
        printListColorNames()
        os.Exit(0)
    }

    if (flagSetColor == nil) {
        os.Exit(0)
    }

    for devInfo := range led.Devices() {
        dev, err := devInfo.Open()
        if err != nil {
            fmt.Println(err)
            continue
        }
        defer func() {
            dev.Close()
        }()

        col := getFlagColor()
        if (col != nil) {
            dev.SetColor(col)
        }

    }

}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package bilateralrpc

import (
	"container/list"
	"errors"
	"fmt"
	svrpc "github.com/bitmark-inc/bilateralrpc/rpc"
	"github.com/bitmark-inc/logger"
	zmq "github.com/pebbe/zmq4"
	"reflect"
	"time"
)

// limits
const (
	tickTime       = 50 * time.Millisecond
	reactorRunTime = 50 * time.Millisecond
)

// sent to all connections value for Call
var SendToAll = []string{}
var SendToOne = []string{}

// type to hold the client/server data
type Bilateral struct {
	// to stop and wait for shutdown
	shutdownAll     chan bool
	rpcShutdown     chan bool
	reactorShutdown chan bool

	// record all connections
	connections map[string]*connect

	// for RPC registration
	server *svrpc.Server

	// this servers identifier
	encrypted   bool
	serverName  string
	networkName string

	// map RPC IDs to their channels
	rpcReturns map[uint32]*rpcClientRequestData

	// communication
	listenSocket   *zmq.Socket
	outgoingSocket *zmq.Socket

	// RPC queues
	// for outgoing RPC
	rpcClientRequestChannel  chan interface{}
	rpcClientResponseChannel chan interface{}

	// for incoming RPC
	rpcServerCallChannel chan rpcServerCallData
	rpcServerBackChannel chan interface{}

	// timeout queue
	timeoutQueue list.List
}

// log channel for debugging
var log *logger.L

// set up the connection (can set plain or encrypted)
// Note that in encrypted mode the public key functions as the server name
// and that the netwokName must match on both sides for connection to be established
//
// for plaintext call as:  NewPlaintext(network_name, server_name)
//
// for encrypted call as:  NewEncrypted(network_name, public_key, private_key)
//      with values from:  pub, priv, err := NewKeypair()
func NewPlaintext(networkName string, serverName string) *Bilateral {
	return createBilateral(networkName, serverName)
}

func NewEncrypted(networkName string, publicKey string, privateKey string) *Bilateral {
	return createBilateral(networkName, publicKey, privateKey)
}

func createBilateral(networkName string, configuration ...string) *Bilateral {

	n := len(configuration)
	if n < 1 || n > 2 {
		panic("NewBilateral must have one or two arguments")
	}

	if nil == log {
		log = logger.New("bilateral")
	}

	twoway := new(Bilateral)

	// initialise global data
	twoway.serverName = configuration[0]
	twoway.networkName = networkName

	twoway.server = svrpc.NewServer()
	twoway.connections = make(map[string]*connect)
	twoway.rpcReturns = make(map[uint32]*rpcClientRequestData)

	// for stopping threads
	twoway.shutdownAll = make(chan bool)

	// RPC buffered streams
	twoway.rpcClientRequestChannel = make(chan interface{}, 20)
	twoway.rpcClientResponseChannel = make(chan interface{}, 20)
	twoway.rpcServerCallChannel = make(chan rpcServerCallData, 20)
	twoway.rpcServerBackChannel = make(chan interface{}, 20)

	log.Infof("server name: %q", twoway.serverName)

	var err error

	twoway.encrypted = false

	switch n {
	case 1: // plaintext connection
		twoway.encrypted = false

		// this is our server side
		twoway.listenSocket, err = createSocket(plainSocket, twoway.serverName, "")
		if nil != err {
			panic(fmt.Sprintf("listen socket: err = %v", err))
		}

		// prepare socket to connect to to multiple upstreams
		twoway.outgoingSocket, err = createSocket(plainSocket, twoway.serverName, "")
		if nil != err {
			panic(fmt.Sprintf("outgoing socket: err = %v", err))
		}

	case 2:
		twoway.encrypted = true

		// this is our server side
		twoway.listenSocket, err = createSocket(serverSocket, twoway.serverName, configuration[1])
		if nil != err {
			panic(fmt.Sprintf("listen socket: err = %v", err))
		}

		// prepare socket to connect to to multiple upstreams
		twoway.outgoingSocket, err = createSocket(clientSocket, twoway.serverName, configuration[1])
		if nil != err {
			panic(fmt.Sprintf("outgoing socket: err = %v", err))
		}
	}

	// set up the reactor to handle all sockets
	reactor := zmq.NewReactor()

	// incoming from downstream clients
	reactor.AddSocket(twoway.listenSocket, zmq.POLLIN,
		func(e zmq.State) error { return twoway.listenHandler() })

	// incoming from upstream servers
	reactor.AddSocket(twoway.outgoingSocket, zmq.POLLIN,
		func(e zmq.State) error { return twoway.replyHandler() })

	reactor.AddChannel(twoway.rpcClientRequestChannel, 5,
		func(item interface{}) error { return twoway.rpcClientRequestHandler(item) })

	reactor.AddChannel(twoway.rpcClientResponseChannel, 5,
		func(item interface{}) error { return twoway.rpcClientResponseHandler(item) })

	reactor.AddChannel(twoway.rpcServerBackChannel, 5,
		func(item interface{}) error { return twoway.rpcBackHandler(item) })

	// start an event loop
	reactor.AddChannelTime(time.Tick(tickTime), 1,
		func(i interface{}) error { return twoway.sender() })

	// background RPC test routines
	go twoway.rpcProcedure()

	// start event loop
	go func() {
		twoway.reactorShutdown = make(chan bool)
		defer close(twoway.reactorShutdown)
		// log <- "reactor start"
		err := reactor.Run(reactorRunTime)
		if nil != err {
			//fmt.Printf("reactor finish: err = %v", err)
			// log <- fmt.Sprintf(COLOUR_RED+"reactor finish: err = %v"+COLOUR_NORMAL, err)
		}
	}()

	return twoway
}

// shutdown all connections, terminate all background processing
func (twoway *Bilateral) Close() {
	log.Info("closing…")

	// disconnect all outgoing connections
	for to := range twoway.connections {
		twoway.DisconnectFrom(to)
	}

	// shutdown background processing
	close(twoway.shutdownAll)

	// close sockets so reactor will stop
	twoway.listenSocket.Close()
	twoway.outgoingSocket.Close()

	log.Info("Close: waiting…")

	// wait for final shutdown
	<-twoway.rpcShutdown
	<-twoway.reactorShutdown

	// close any remaining channels
	close(twoway.rpcClientRequestChannel)
	close(twoway.rpcClientResponseChannel)
	close(twoway.rpcServerCallChannel)
	close(twoway.rpcServerBackChannel)

	// terminate all outstanding calls
	for _, request := range twoway.rpcReturns {
		twoway.finishRequest(request)
	}

	// clear the timeout queue
	for e := twoway.timeoutQueue.Front(); nil != e; e = e.Prev() {
		twoway.timeoutQueue.Remove(e)
	}
	log.Info("Close: complete")
}

// listen for incomming requests
func (twoway *Bilateral) ListenOn(address string) error {
	log.Infof("set listen on: %s", address)
	return twoway.listenSocket.Bind(address)
}

// connect to a remote
func (twoway *Bilateral) ConnectTo(name string, address string) error {
	// do not make a loopback connection
	if twoway.serverName == name {
		return errors.New("loopback forbidden")
	}

	if _, exists := twoway.connections[name]; exists {
		return errors.New("duplicate connection")
	}

	log.Infof("connect to: %s @ %s", name, address)

	twoway.connections[name] = &connect{
		timestamp: time.Now().Add(FIRST_START_TIME),
		name:      name,
		address:   address,
		state:     stateWaiting,
		joinCount: 0,
		backoff:   0,
		outgoing:  true,
		tick:      0,
	}

	return nil
}

// disconnect from a remote
func (twoway *Bilateral) DisconnectFrom(name string) error {
	_, exists := twoway.connections[name]
	if !exists {
		return errors.New("no existing connection")
	}
	log.Infof("disconnect from: %s", name)
	delete(twoway.connections, name)
	return nil
}

// count active connections
func (twoway *Bilateral) ConnectionCount() int {
	count := 0
	for _, c := range twoway.connections {
		if stateConnected == c.state || stateCheck == c.state || stateServing == c.state {
			count += 1
		}
	}
	return count
}

// register a callback object
func (twoway *Bilateral) Register(receiver interface{}) error {
	return twoway.server.Register(receiver)
}

// get a list of acive peers names
func (twoway *Bilateral) ActiveConnections() []string {
	active := make([]string, 0, len(twoway.connections))
	for name, c := range twoway.connections {
		if stateConnected == c.state || stateCheck == c.state || stateServing == c.state {
			active = append(active, name)
		}
	}
	return active
}

// rpc call routine and receive reply, waiting if necessary
// to can be set to SendToAll to do a broadcast
func (twoway *Bilateral) Call(to []string, method string, args interface{}, results interface{}, wait time.Duration) error {

	if nil != to && 0 == len(to) {
		to = nil
	}

	if 0 == wait {
		wait = CALL_TIMEOUT
	}

	select {
	case <-twoway.shutdownAll:
		return errors.New("RPC system shutting down")
	default:
	}

	id := nonce()

	ptr := reflect.TypeOf(results)
	if reflect.Ptr != ptr.Kind() && !reflect.ValueOf(results).IsNil() && reflect.Slice != ptr.Elem().Kind() {
		return errors.New("must be a non-nil pointer to slice")
	}

	theSlice := ptr.Elem()

	// ptr to slice of 's' - some kind of struct
	theStruct := theSlice.Elem()
	if reflect.Struct != theStruct.Kind() || 3 != theStruct.NumField() {
		return errors.New("must be a struct with three fields")
	}

	fromField, hasFrom := theStruct.FieldByName("From")
	_, hasReply := theStruct.FieldByName("Reply")
	errField, hasErr := theStruct.FieldByName("Err")

	if !hasFrom || !hasReply || !hasErr {
		return errors.New("must be a struct with From, Reply and Err fields")
	}

	if reflect.String != fromField.Type.Kind() {
		return errors.New("struct From field must be string")
	}

	if reflect.Interface != errField.Type.Kind() {
		return errors.New("struct Err field must be error")
	}

	done := make(chan *rpcClientRequestData)

	log.Infof("send for method: %s", method)
	twoway.rpcClientRequestChannel <- &rpcClientRequestData{
		id:         id,
		to:         to,
		wait:       wait,
		method:     method,
		args:       args,
		structType: theStruct,
		done:       done,
		reply:      nil, // added later
		count:      0,   // added later
	}

	log.Infof("wait for result for method: %s", method)
	// the processed request will be returned here
	request := <-done
	log.Infof("result for method: %s : %v", method, request)

	if nil == request.reply {
		return errors.New("no results")
	}

	received := reflect.MakeSlice(theSlice, 0, len(to))
	for r := range request.reply {
		received = reflect.Append(received, r.Elem())
	}
	reflect.ValueOf(results).Elem().Set(received)
	log.Infof("final for method: %s : %v", method, results)

	return nil
}

// rpc cast routine - no reply will be sent by remote
// to can be set to SendToAll to do a broadcast
func (twoway *Bilateral) Cast(to []string, method string, args interface{}) error {

	if nil != to && 0 == len(to) {
		to = nil
	}

	select {
	case <-twoway.shutdownAll:
		return errors.New("RPC system shutting down")
	default:
	}

	id := nonce()
	twoway.rpcClientRequestChannel <- &rpcClientRequestData{
		id:         id,
		to:         to,
		wait:       CALL_TIMEOUT,
		method:     method,
		args:       args,
		structType: nil,
		done:       nil,
		reply:      nil, // added later
		count:      0,   // added later
	}

	return nil
}
<commit_msg>fix reactor terminates randomly bug<commit_after>// Copyright (c) 2014-2015 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package bilateralrpc

import (
	"container/list"
	"errors"
	"fmt"
	svrpc "github.com/bitmark-inc/bilateralrpc/rpc"
	"github.com/bitmark-inc/logger"
	zmq "github.com/pebbe/zmq4"
	"reflect"
	"syscall"
	"time"
)

// limits
const (
	tickTime       = 50 * time.Millisecond
	reactorRunTime = 50 * time.Millisecond
)

// sent to all connections value for Call
var SendToAll = []string{}
var SendToOne = []string{}

// type to hold the client/server data
type Bilateral struct {
	// to stop and wait for shutdown
	shutdownAll     chan bool
	rpcShutdown     chan bool
	reactorShutdown chan bool

	// record all connections
	connections map[string]*connect

	// for RPC registration
	server *svrpc.Server

	// this servers identifier
	encrypted   bool
	serverName  string
	networkName string

	// map RPC IDs to their channels
	rpcReturns map[uint32]*rpcClientRequestData

	// communication
	listenSocket   *zmq.Socket
	outgoingSocket *zmq.Socket

	// RPC queues
	// for outgoing RPC
	rpcClientRequestChannel  chan interface{}
	rpcClientResponseChannel chan interface{}

	// for incoming RPC
	rpcServerCallChannel chan rpcServerCallData
	rpcServerBackChannel chan interface{}

	// timeout queue
	timeoutQueue list.List
}

// log channel for debugging
var log *logger.L

// set up the connection (can set plain or encrypted)
// Note that in encrypted mode the public key functions as the server name
// and that the netwokName must match on both sides for connection to be established
//
// for plaintext call as:  NewPlaintext(network_name, server_name)
//
// for encrypted call as:  NewEncrypted(network_name, public_key, private_key)
//      with values from:  pub, priv, err := NewKeypair()
func NewPlaintext(networkName string, serverName string) *Bilateral {
	return createBilateral(networkName, serverName)
}

func NewEncrypted(networkName string, publicKey string, privateKey string) *Bilateral {
	return createBilateral(networkName, publicKey, privateKey)
}

func createBilateral(networkName string, configuration ...string) *Bilateral {

	n := len(configuration)
	if n < 1 || n > 2 {
		panic("NewBilateral must have one or two arguments")
	}

	if nil == log {
		log = logger.New("bilateral")
	}

	twoway := new(Bilateral)

	// initialise global data
	twoway.serverName = configuration[0]
	twoway.networkName = networkName

	twoway.server = svrpc.NewServer()
	twoway.connections = make(map[string]*connect)
	twoway.rpcReturns = make(map[uint32]*rpcClientRequestData)

	// for stopping threads
	twoway.shutdownAll = make(chan bool)

	// RPC buffered streams
	twoway.rpcClientRequestChannel = make(chan interface{}, 20)
	twoway.rpcClientResponseChannel = make(chan interface{}, 20)
	twoway.rpcServerCallChannel = make(chan rpcServerCallData, 20)
	twoway.rpcServerBackChannel = make(chan interface{}, 20)

	log.Infof("server name: %q", twoway.serverName)

	var err error

	twoway.encrypted = false

	switch n {
	case 1: // plaintext connection
		twoway.encrypted = false

		// this is our server side
		twoway.listenSocket, err = createSocket(plainSocket, twoway.serverName, "")
		if nil != err {
			panic(fmt.Sprintf("listen socket: err = %v", err))
		}

		// prepare socket to connect to to multiple upstreams
		twoway.outgoingSocket, err = createSocket(plainSocket, twoway.serverName, "")
		if nil != err {
			panic(fmt.Sprintf("outgoing socket: err = %v", err))
		}

	case 2:
		twoway.encrypted = true

		// this is our server side
		twoway.listenSocket, err = createSocket(serverSocket, twoway.serverName, configuration[1])
		if nil != err {
			panic(fmt.Sprintf("listen socket: err = %v", err))
		}

		// prepare socket to connect to to multiple upstreams
		twoway.outgoingSocket, err = createSocket(clientSocket, twoway.serverName, configuration[1])
		if nil != err {
			panic(fmt.Sprintf("outgoing socket: err = %v", err))
		}
	}

	// set up the reactor to handle all sockets
	reactor := zmq.NewReactor()

	// incoming from downstream clients
	reactor.AddSocket(twoway.listenSocket, zmq.POLLIN,
		func(e zmq.State) error { return twoway.listenHandler() })

	// incoming from upstream servers
	reactor.AddSocket(twoway.outgoingSocket, zmq.POLLIN,
		func(e zmq.State) error { return twoway.replyHandler() })

	reactor.AddChannel(twoway.rpcClientRequestChannel, 5,
		func(item interface{}) error { return twoway.rpcClientRequestHandler(item) })

	reactor.AddChannel(twoway.rpcClientResponseChannel, 5,
		func(item interface{}) error { return twoway.rpcClientResponseHandler(item) })

	reactor.AddChannel(twoway.rpcServerBackChannel, 5,
		func(item interface{}) error { return twoway.rpcBackHandler(item) })

	// start an event loop
	reactor.AddChannelTime(time.Tick(tickTime), 1,
		func(i interface{}) error { return twoway.sender() })

	// background RPC test routines
	go twoway.rpcProcedure()

	// start event loop
	go func() {
		twoway.reactorShutdown = make(chan bool)
		defer close(twoway.reactorShutdown)
		log.Info("reactor start")
		for {
			// note: re-run reactor if its internal poll fails with "interrupted system call"
			err := reactor.Run(reactorRunTime)
			if nil == err {
				break // normal termination
			} else if  zmq.Errno(syscall.EINTR) != zmq.AsErrno(err) {
				log.Errorf("reactor failed: err = %v", err)
				break
			}
			log.Errorf("reactor retry: err = %v", err)
		}
		log.Info("reactor stopped")
	}()

	return twoway
}

// shutdown all connections, terminate all background processing
func (twoway *Bilateral) Close() {
	log.Info("closing…")

	// disconnect all outgoing connections
	for to := range twoway.connections {
		twoway.DisconnectFrom(to)
	}

	// shutdown background processing
	close(twoway.shutdownAll)

	// close sockets so reactor will stop
	twoway.listenSocket.Close()
	twoway.outgoingSocket.Close()

	log.Info("Close: waiting…")

	// wait for final shutdown
	<-twoway.rpcShutdown
	<-twoway.reactorShutdown

	// close any remaining channels
	close(twoway.rpcClientRequestChannel)
	close(twoway.rpcClientResponseChannel)
	close(twoway.rpcServerCallChannel)
	close(twoway.rpcServerBackChannel)

	// terminate all outstanding calls
	for _, request := range twoway.rpcReturns {
		twoway.finishRequest(request)
	}

	// clear the timeout queue
	for e := twoway.timeoutQueue.Front(); nil != e; e = e.Prev() {
		twoway.timeoutQueue.Remove(e)
	}
	log.Info("Close: complete")
}

// listen for incomming requests
func (twoway *Bilateral) ListenOn(address string) error {
	log.Infof("set listen on: %s", address)
	return twoway.listenSocket.Bind(address)
}

// connect to a remote
func (twoway *Bilateral) ConnectTo(name string, address string) error {
	// do not make a loopback connection
	if twoway.serverName == name {
		return errors.New("loopback forbidden")
	}

	if _, exists := twoway.connections[name]; exists {
		return errors.New("duplicate connection")
	}

	log.Infof("connect to: %s @ %s", name, address)

	twoway.connections[name] = &connect{
		timestamp: time.Now().Add(FIRST_START_TIME),
		name:      name,
		address:   address,
		state:     stateWaiting,
		joinCount: 0,
		backoff:   0,
		outgoing:  true,
		tick:      0,
	}

	return nil
}

// disconnect from a remote
func (twoway *Bilateral) DisconnectFrom(name string) error {
	_, exists := twoway.connections[name]
	if !exists {
		return errors.New("no existing connection")
	}
	log.Infof("disconnect from: %s", name)
	delete(twoway.connections, name)
	return nil
}

// count active connections
func (twoway *Bilateral) ConnectionCount() int {
	count := 0
	for _, c := range twoway.connections {
		if stateConnected == c.state || stateCheck == c.state || stateServing == c.state {
			count += 1
		}
	}
	return count
}

// register a callback object
func (twoway *Bilateral) Register(receiver interface{}) error {
	return twoway.server.Register(receiver)
}

// get a list of acive peers names
func (twoway *Bilateral) ActiveConnections() []string {
	active := make([]string, 0, len(twoway.connections))
	for name, c := range twoway.connections {
		if stateConnected == c.state || stateCheck == c.state || stateServing == c.state {
			active = append(active, name)
		}
	}
	return active
}

// rpc call routine and receive reply, waiting if necessary
// to can be set to SendToAll to do a broadcast
func (twoway *Bilateral) Call(to []string, method string, args interface{}, results interface{}, wait time.Duration) error {

	if nil != to && 0 == len(to) {
		to = nil
	}

	if 0 == wait {
		wait = CALL_TIMEOUT
	}

	select {
	case <-twoway.shutdownAll:
		return errors.New("RPC system shutting down")
	default:
	}

	id := nonce()

	ptr := reflect.TypeOf(results)
	if reflect.Ptr != ptr.Kind() && !reflect.ValueOf(results).IsNil() && reflect.Slice != ptr.Elem().Kind() {
		return errors.New("must be a non-nil pointer to slice")
	}

	theSlice := ptr.Elem()

	// ptr to slice of 's' - some kind of struct
	theStruct := theSlice.Elem()
	if reflect.Struct != theStruct.Kind() || 3 != theStruct.NumField() {
		return errors.New("must be a struct with three fields")
	}

	fromField, hasFrom := theStruct.FieldByName("From")
	_, hasReply := theStruct.FieldByName("Reply")
	errField, hasErr := theStruct.FieldByName("Err")

	if !hasFrom || !hasReply || !hasErr {
		return errors.New("must be a struct with From, Reply and Err fields")
	}

	if reflect.String != fromField.Type.Kind() {
		return errors.New("struct From field must be string")
	}

	if reflect.Interface != errField.Type.Kind() {
		return errors.New("struct Err field must be error")
	}

	done := make(chan *rpcClientRequestData)

	log.Infof("send for method: %s", method)
	twoway.rpcClientRequestChannel <- &rpcClientRequestData{
		id:         id,
		to:         to,
		wait:       wait,
		method:     method,
		args:       args,
		structType: theStruct,
		done:       done,
		reply:      nil, // added later
		count:      0,   // added later
	}

	log.Infof("wait for result for method: %s", method)
	// the processed request will be returned here
	request := <-done
	log.Infof("result for method: %s : %v", method, request)

	if nil == request.reply {
		return errors.New("no results")
	}

	received := reflect.MakeSlice(theSlice, 0, len(to))
	for r := range request.reply {
		received = reflect.Append(received, r.Elem())
	}
	reflect.ValueOf(results).Elem().Set(received)
	log.Infof("final for method: %s : %v", method, results)

	return nil
}

// rpc cast routine - no reply will be sent by remote
// to can be set to SendToAll to do a broadcast
func (twoway *Bilateral) Cast(to []string, method string, args interface{}) error {

	if nil != to && 0 == len(to) {
		to = nil
	}

	select {
	case <-twoway.shutdownAll:
		return errors.New("RPC system shutting down")
	default:
	}

	id := nonce()
	twoway.rpcClientRequestChannel <- &rpcClientRequestData{
		id:         id,
		to:         to,
		wait:       CALL_TIMEOUT,
		method:     method,
		args:       args,
		structType: nil,
		done:       nil,
		reply:      nil, // added later
		count:      0,   // added later
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

var noPassthrough = flag.Bool("no-passthrough", false, "Don't print non-benchmark lines")

type BenchOutput struct {
	Name             string
	Iterations       int64
	TimePerIteration time.Duration
	// Optional fields
	BytesPerSecond  *float64
	BytesAllocPerOp *int64
	AllocsPerOp     *int64
}

type BenchOutputGroup struct {
	Lines []*BenchOutput
	// Columns which are in use
	BytesPresent      bool
	BytesAllocPresent bool
	AllocsPresent     bool
}

type Table struct {
	MaxLengths []int
	Cells      [][]string
}

func (g *BenchOutputGroup) String() string {
	if len(g.Lines) == 0 {
		return ""
	}
	columnNames := []string{"benchmark", "iter", "time/iter"}
	if g.BytesPresent {
		columnNames = append(columnNames, "throughput")
	}
	if g.BytesAllocPresent {
		columnNames = append(columnNames, "bytes alloc")
	}
	if g.AllocsPresent {
		columnNames = append(columnNames, "allocs")
	}
	table := &Table{Cells: [][]string{columnNames}}

	var underlines []string
	for _, name := range columnNames {
		underlines = append(underlines, strings.Repeat("-", len(name)))
	}
	table.Cells = append(table.Cells, underlines)
	timeFormatFunc := g.TimeFormatFunc()

	for _, line := range g.Lines {
		row := []string{line.Name, FormatIterations(line.Iterations), timeFormatFunc(line.TimePerIteration)}
		if g.BytesPresent {
			row = append(row, FormatBytesPerSecond(line.BytesPerSecond))
		}
		if g.BytesAllocPresent {
			row = append(row, FormatBytesAllocPerOp(line.BytesAllocPerOp))
		}
		if g.AllocsPresent {
			row = append(row, FormatAllocsPerOp(line.AllocsPerOp))
		}
		table.Cells = append(table.Cells, row)
	}
	for i := range columnNames {
		maxLength := 0
		for _, row := range table.Cells {
			if len(row[i]) > maxLength {
				maxLength = len(row[i])
			}
		}
		table.MaxLengths = append(table.MaxLengths, maxLength)
	}
	var buf bytes.Buffer
	for _, row := range table.Cells {
		for i, cell := range row {
			var format string
			switch i {
			case 0:
				format = "%%-%ds   "
			case len(row) - 1:
				format = "%%%ds"
			default:
				format = "%%%ds   "
			}
			fmt.Fprintf(&buf, fmt.Sprintf(format, table.MaxLengths[i]), cell)
		}
		fmt.Fprint(&buf, "\n")
	}
	return buf.String()
}

func FormatIterations(iter int64) string {
	return strconv.FormatInt(iter, 10)
}

func (g *BenchOutputGroup) TimeFormatFunc() func(time.Duration) string {
	// Find the smallest time
	smallest := g.Lines[0].TimePerIteration
	for _, line := range g.Lines[1:] {
		if line.TimePerIteration < smallest {
			smallest = line.TimePerIteration
		}
	}
	switch {
	case smallest < 10000*time.Nanosecond:
		return func(d time.Duration) string {
			return fmt.Sprintf("%d ns/op", d.Nanoseconds())
		}
	case smallest < time.Millisecond:
		return func(d time.Duration) string {
			return fmt.Sprintf("%.2f μs/op", float64(d.Nanoseconds())/1000)
		}
	case smallest < 10*time.Second:
		return func(d time.Duration) string {
			return fmt.Sprintf("%.2f ms/op", d.Seconds()*1000)
		}
	default:
		return func(d time.Duration) string {
			return fmt.Sprintf("%.2f s/op", d.Seconds())
		}
	}
}

func FormatBytesPerSecond(b *float64) string {
	if b == nil {
		return ""
	}
	return fmt.Sprintf("%.2f MB/s", *b/1e6)
}

func FormatBytesAllocPerOp(b *int64) string {
	if b == nil {
		return ""
	}
	return fmt.Sprintf("%d B/op", *b)
}

func FormatAllocsPerOp(a *int64) string {
	if a == nil {
		return ""
	}
	return fmt.Sprintf("%d allocs/op", *a)
}

func (g *BenchOutputGroup) AddLine(line *BenchOutput) {
	g.Lines = append(g.Lines, line)
	if line.BytesPerSecond != nil {
		g.BytesPresent = true
	}
	if line.BytesAllocPerOp != nil {
		g.BytesAllocPresent = true
	}
	if line.AllocsPerOp != nil {
		g.AllocsPresent = true
	}
}

var (
	benchLineMatcher  = regexp.MustCompile(`^Benchmark.*\t.*\d+`)
	okLineMatcher     = regexp.MustCompile(`^ok\s`)
	notBenchLineErr   = errors.New("Not a bench line")
	benchLineParseErr = errors.New("Unable to parse benchmark output line")
)

func ParseLine(line string) (*BenchOutput, error) {
	if !benchLineMatcher.MatchString(line) {
		return nil, notBenchLineErr
	}
	fields := strings.Split(line, "\t")
	if len(fields) < 3 {
		return nil, notBenchLineErr
	}
	var err error
	output := &BenchOutput{Name: strings.TrimSpace(fields[0])}
	output.Iterations, err = strconv.ParseInt(strings.TrimSpace(fields[1]), 10, 64)
	if err != nil {
		return nil, notBenchLineErr
	}
	for _, field := range fields[2:] {
		parts := strings.Split(strings.TrimSpace(field), " ")
		if len(parts) != 2 {
			return nil, benchLineParseErr
		}
		if parts[1] == "MB/s" {
			value, err := strconv.ParseFloat(parts[0], 64)
			if err != nil {
				return nil, benchLineParseErr
			}
			value *= 1e6
			output.BytesPerSecond = &value
			continue
		}
		value, err := strconv.ParseInt(parts[0], 10, 64)
		if err != nil {
			return nil, benchLineParseErr
		}
		switch parts[1] {
		case "ns/op":
			output.TimePerIteration = time.Duration(value)
		case "B/op":
			output.BytesAllocPerOp = &value
		case "allocs/op":
			output.AllocsPerOp = &value
		default:
			return nil, benchLineParseErr
		}
	}
	return output, nil
}

func main() {
	flag.Parse()
	currentBenchmark := &BenchOutputGroup{}
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		text := scanner.Text()
		line, err := ParseLine(text)
		switch err {
		case notBenchLineErr:
			if okLineMatcher.MatchString(text) {
				fmt.Print(currentBenchmark)
				currentBenchmark = &BenchOutputGroup{}
			}
			if !*noPassthrough {
				fmt.Println(text)
			}
		case nil:
			currentBenchmark.AddLine(line)
		default:
			fmt.Fprintln(os.Stderr, "prettybench unrecognized line:")
			fmt.Println(text)
		}
	}
	if err := scanner.Err(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<commit_msg>reuse benchcmp's parser<commit_after>package main

import (
	"bufio"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"

	benchcmp "golang.org/x/tools/cmd/benchcmp"
)

var noPassthrough = flag.Bool("no-passthrough", false, "Don't print non-benchmark lines")

type BenchOutputGroup struct {
	Lines []*benchcmp.Bench
	// Columns which are in use
	MegaBytesPresent  bool
	BytesAllocPresent bool
	AllocsPresent     bool
}

type Table struct {
	MaxLengths []int
	Cells      [][]string
}

func (g *BenchOutputGroup) String() string {
	if len(g.Lines) == 0 {
		return ""
	}
	columnNames := []string{"benchmark", "iter", "time/iter"}
	if g.MegaBytesPresent {
		columnNames = append(columnNames, "throughput")
	}
	if g.BytesAllocPresent {
		columnNames = append(columnNames, "bytes alloc")
	}
	if g.AllocsPresent {
		columnNames = append(columnNames, "allocs")
	}
	table := &Table{Cells: [][]string{columnNames}}

	var underlines []string
	for _, name := range columnNames {
		underlines = append(underlines, strings.Repeat("-", len(name)))
	}
	table.Cells = append(table.Cells, underlines)
	timeFormatFunc := g.TimeFormatFunc()

	for _, line := range g.Lines {
		row := []string{line.Name, FormatIterations(line.N), timeFormatFunc(line.NsOp)}
		if g.MegaBytesPresent {
			row = append(row, FormatMegaBytesPerSecond(line))
		}
		if g.BytesAllocPresent {
			row = append(row, FormatBytesAllocPerOp(line))
		}
		if g.AllocsPresent {
			row = append(row, FormatAllocsPerOp(line))
		}
		table.Cells = append(table.Cells, row)
	}
	for i := range columnNames {
		maxLength := 0
		for _, row := range table.Cells {
			if len(row[i]) > maxLength {
				maxLength = len(row[i])
			}
		}
		table.MaxLengths = append(table.MaxLengths, maxLength)
	}
	var buf bytes.Buffer
	for _, row := range table.Cells {
		for i, cell := range row {
			var format string
			switch i {
			case 0:
				format = "%%-%ds   "
			case len(row) - 1:
				format = "%%%ds"
			default:
				format = "%%%ds   "
			}
			fmt.Fprintf(&buf, fmt.Sprintf(format, table.MaxLengths[i]), cell)
		}
		fmt.Fprint(&buf, "\n")
	}
	return buf.String()
}

func FormatIterations(iter int) string {
	return strconv.FormatInt(int64(iter), 10)
}

func (g *BenchOutputGroup) TimeFormatFunc() func(float64) string {
	// Find the smallest time
	smallest := g.Lines[0].NsOp
	for _, line := range g.Lines[1:] {
		if line.NsOp < smallest {
			smallest = line.NsOp
		}
	}
	switch {
	case smallest < float64(10000*time.Nanosecond):
		return func(ns float64) string {
			return fmt.Sprintf("%.2f ns/op", ns)
		}
	case smallest < float64(time.Millisecond):
		return func(ns float64) string {
			return fmt.Sprintf("%.2f μs/op", ns/1000)
		}
	case smallest < float64(10*time.Second):
		return func(ns float64) string {
			return fmt.Sprintf("%.2f ms/op", (ns / 1e6))
		}
	default:
		return func(ns float64) string {
			return fmt.Sprintf("%.2f s/op", ns/1e9)
		}
	}
}

func FormatMegaBytesPerSecond(l *benchcmp.Bench) string {
	if (l.Measured & benchcmp.MbS) == 0 {
		return ""
	}
	return fmt.Sprintf("%.2f MB/s", l.MbS)
}

func FormatBytesAllocPerOp(l *benchcmp.Bench) string {
	if (l.Measured & benchcmp.BOp) == 0 {
		return ""
	}
	return fmt.Sprintf("%d B/op", l.BOp)
}

func FormatAllocsPerOp(l *benchcmp.Bench) string {
	if (l.Measured & benchcmp.AllocsOp) == 0 {
		return ""
	}
	return fmt.Sprintf("%d allocs/op", l.AllocsOp)
}

func (g *BenchOutputGroup) AddLine(line *benchcmp.Bench) {
	g.Lines = append(g.Lines, line)
	if (line.Measured & benchcmp.MbS) > 0 {
		g.MegaBytesPresent = true
	}
	if (line.Measured & benchcmp.BOp) > 0 {
		g.BytesAllocPresent = true
	}
	if (line.Measured & benchcmp.AllocsOp) > 0 {
		g.AllocsPresent = true
	}
}

var (
	benchLineMatcher = regexp.MustCompile(`^Benchmark.*\t.*\d+`)
	okLineMatcher    = regexp.MustCompile(`^ok\s`)
	notBenchLineErr  = errors.New("Not a bench line")
)

func ParseLine(line string) (*benchcmp.Bench, error) {
	if !benchLineMatcher.MatchString(line) {
		return nil, notBenchLineErr
	}
	fields := strings.Split(line, "\t")
	if len(fields) < 3 {
		return nil, notBenchLineErr
	}

	return benchcmp.ParseLine(line)
}

func main() {
	flag.Parse()
	currentBenchmark := &BenchOutputGroup{}
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		text := scanner.Text()
		line, err := ParseLine(text)
		switch err {
		case notBenchLineErr:
			if okLineMatcher.MatchString(text) {
				fmt.Print(currentBenchmark)
				currentBenchmark = &BenchOutputGroup{}
			}
			if !*noPassthrough {
				fmt.Println(text)
			}
		case nil:
			currentBenchmark.AddLine(line)
		default:
			fmt.Fprintln(os.Stderr, "prettybench unrecognized line:")
			fmt.Println(text)
		}
	}
	if err := scanner.Err(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
	"strings"
)

var DefaultTemplate string

func parseRequest(r *http.Request) (repo, doc string) {
	path := strings.Split(r.RequestURI, "/")
	repo = path[1]

	if len(path) < 3 || (len(path) == 3 && strings.HasSuffix(r.RequestURI, "/")) {
		doc = "index"
	} else {
		doc = strings.Join(path[2:], "/")
		if strings.HasSuffix(doc, "/") {
			doc = doc[:len(doc)-1]
		}
	}
	return
}

func fetchAndRenderDoc(user, repo, doc string) (string, error) {
	template := make(chan string)
	go func() {
		buf, err := ioutil.ReadFile("docs/template.html")
		if err != nil {
			template <- DefaultTemplate
			return
		}
		template <- string(buf)
	}()
	buf, err := ioutil.ReadFile("docs/" + doc + ".md")
	if err != nil {
		return "# Page not found", err
	}

	bodyStr := string(buf)

	url := "https://api.github.com/markdown/raw"
	if os.Getenv("ACCESS_TOKEN") != "" {
		url += "?access_token=" + os.Getenv("ACCESS_TOKEN")
	}
	resp, err := http.Post(url, "text/x-markdown", strings.NewReader(bodyStr))
	if err != nil {
		return "", err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	output := strings.Replace(<-template, "{{CONTENT}}", string(body), 1)
	if user != "" {
		output = strings.Replace(output, "{{NAME}}", repo, -1)
	}
	if repo != "" {
		output = strings.Replace(output, "{{USER}}", user, -1)
	}
	return output, nil
}

func grabUserAndRepo() (user, repo string) {
	cmd := exec.Command("git", "config", "--get", "remote.origin.url")
	if out, err := cmd.CombinedOutput(); err != nil {
		log.Printf("Error fetching github user and repository\nERROR: %s", err)
	} else {
		output := strings.Trim(string(out), "\n")
		reg := regexp.MustCompile(`([^:/]+)/([\w.-]+)\.git$`)
		matches := reg.FindStringSubmatch(output)

		if len(matches) > 0 {
			user = matches[1]
			repo = matches[2]
		} else {
			log.Fatalf("Unable to parse your GitHub user and repository from '%s'. Please open an issue on https://github.com/fgrehm/previewdocs", output)
		}
	}

	return
}

func main() {
	if os.Getenv("ACCESS_TOKEN") == "" {
		log.Println("WARNING: ACCESS_TOKEN was not found, you'll be subject to GitHub's Rate Limiting of 60 requests per hour. " +
			"Please read http://developer.github.com/v3/#rate-limiting for more information")
	}

	port := os.Getenv("PORT")
	if port == "" {
		port = "8888"
	}

	resp, err := http.Get("https://raw.github.com/progrium/viewdocs/master/docs/template.html")
	if err != nil || resp.StatusCode == 404 {
		log.Fatal("Unable to fetch default template")
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		log.Fatal(err)
	}
	DefaultTemplate = string(body)

	user, gitHubRepo := grabUserAndRepo()

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.RequestURI == "/" {
			http.Redirect(w, r, "/" + gitHubRepo, 301)
			return
		}
		if r.RequestURI == "/favicon.ico" {
			return
		}
		switch r.Method {
		case "GET":
			requestedRepo, doc := parseRequest(r)
			if requestedRepo != gitHubRepo {
				w.WriteHeader(http.StatusNotFound)
				w.Write([]byte("Invalid repository '" + requestedRepo +  "'"))
				return
			}
			log.Printf("Building docs for '%s'", doc)
			output, err := fetchAndRenderDoc(user, gitHubRepo, doc)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				w.Write([]byte(err.Error()))
				return
			}
			w.Write([]byte(output))
		default:
			w.WriteHeader(http.StatusMethodNotAllowed)
		}
	})
	log.Println("Listening on port " + port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}
<commit_msg>Backport @marksteve changes to fix relative linking from https://github.com/progrium/viewdocs/pull/9<commit_after>package main

import (
	"bytes"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"

	"code.google.com/p/go.net/html"
)

var DefaultTemplate string

func parseRequest(r *http.Request) (repo, doc string) {
	path := strings.Split(r.RequestURI, "/")
	repo = path[1]

	if len(path) < 3 || (len(path) == 3 && strings.HasSuffix(r.RequestURI, "/")) {
		doc = "index.md"
	} else {
		doc = strings.Join(path[2:], "/")
		if strings.HasSuffix(doc, "/") {
			doc = doc[:len(doc)-1]
		}
	}
	return
}

func fixRelativeLinks(doc string, repo string, body string) (string, error) {
	n, err := html.Parse(strings.NewReader(string(body)))
	if err != nil {
		return "", err
	}
	var f func(*html.Node)
	f = func(n *html.Node) {
		if n.Type == html.ElementNode && n.Data == "a" {
			for i, a := range n.Attr {
				if a.Key == "href" {
					fs := strings.Index(a.Val, "/")
					fc := strings.Index(a.Val, ":")
					fh := strings.Index(a.Val, "#")
					if fs == 0 || fh == 0 ||
					(fc >= 0 && fc < fs) ||
					(fh >= 0 && fh < fs) {
						continue
					}
					dir := path.Dir(doc)
					n.Attr[i].Val = "/" + repo + "/" + dir + "/" + a.Val
				}
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			f(c)
		}
	}
	f(n)
	b := new(bytes.Buffer)
	if err := html.Render(b, n); err != nil {
		return "", err
	}
	return b.String(), nil
}

func fetchAndRenderDoc(user, repo, doc string) (string, error) {
	template := make(chan string)
	go func() {
		buf, err := ioutil.ReadFile("docs/template.html")
		if err != nil {
			template <- DefaultTemplate
			return
		}
		template <- string(buf)
	}()

	// https://github.com/github/markup/blob/master/lib/github/markups.rb#L1
	mdExts := map[string]bool{
		".md":        true,
		".mkdn":      true,
		".mdwn":      true,
		".mdown":     true,
		".markdown":  true,
		".litcoffee": true,
	}
	if ok, _ := mdExts[path.Ext(doc)]; !ok {
		doc += ".md"
	}

	buf, err := ioutil.ReadFile("docs/" + doc)
	if err != nil {
		return "# Page not found", err
	}

	bodyStr := string(buf)

	url := "https://api.github.com/markdown/raw"
	if os.Getenv("ACCESS_TOKEN") != "" {
		url += "?access_token=" + os.Getenv("ACCESS_TOKEN")
	}
	resp, err := http.Post(url, "text/x-markdown", strings.NewReader(bodyStr))
	if err != nil {
		return "", err
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	// Fix relative links
	bodyStr, err = fixRelativeLinks(doc, repo, string(body))
	if err != nil {
		return "", err
	}

	output := strings.Replace(<-template, "{{CONTENT}}", bodyStr, 1)
	if user != "" {
		output = strings.Replace(output, "{{NAME}}", repo, -1)
	}
	if repo != "" {
		output = strings.Replace(output, "{{USER}}", user, -1)
	}
	return output, nil
}

func grabUserAndRepo() (user, repo string) {
	cmd := exec.Command("git", "config", "--get", "remote.origin.url")
	if out, err := cmd.CombinedOutput(); err != nil {
		log.Printf("Error fetching github user and repository\nERROR: %s", err)
	} else {
		output := strings.Trim(string(out), "\n")
		reg := regexp.MustCompile(`([^:/]+)/([\w.-]+)\.git$`)
		matches := reg.FindStringSubmatch(output)

		if len(matches) > 0 {
			user = matches[1]
			repo = matches[2]
		} else {
			log.Fatalf("Unable to parse your GitHub user and repository from '%s'. Please open an issue on https://github.com/fgrehm/previewdocs", output)
		}
	}

	return
}

func main() {
	if os.Getenv("ACCESS_TOKEN") == "" {
		log.Println("WARNING: ACCESS_TOKEN was not found, you'll be subject to GitHub's Rate Limiting of 60 requests per hour. " +
			"Please read http://developer.github.com/v3/#rate-limiting for more information")
	}

	port := os.Getenv("PORT")
	if port == "" {
		port = "8888"
	}

	resp, err := http.Get("https://raw.github.com/progrium/viewdocs/master/docs/template.html")
	if err != nil || resp.StatusCode == 404 {
		log.Fatal("Unable to fetch default template")
	}
	body, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		log.Fatal(err)
	}
	DefaultTemplate = string(body)

	user, gitHubRepo := grabUserAndRepo()

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.RequestURI == "/" {
			http.Redirect(w, r, "/" + gitHubRepo, 301)
			return
		}
		if r.RequestURI == "/favicon.ico" {
			return
		}
		switch r.Method {
		case "GET":
			requestedRepo, doc := parseRequest(r)
			if requestedRepo != gitHubRepo {
				w.WriteHeader(http.StatusNotFound)
				w.Write([]byte("Invalid repository '" + requestedRepo +  "'"))
				return
			}
			log.Printf("Building docs for '%s'", doc)
			output, err := fetchAndRenderDoc(user, gitHubRepo, doc)
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				w.Write([]byte(err.Error()))
				return
			}
			w.Write([]byte(output))
		default:
			w.WriteHeader(http.StatusMethodNotAllowed)
		}
	})
	log.Println("Listening on port " + port)
	log.Fatal(http.ListenAndServe(":"+port, nil))
}
<|endoftext|>


<commit_before>package prime

import (
    "fmt"
    "math/big"
    "sync"
)

var big0 = big.NewInt(0)
var big2 = big.NewInt(2)
var big3 = big.NewInt(3)

var primes = []*big.Int{big2, big3}
var pMutex = new(sync.Mutex)

type Primes struct {
    i int // TODO more scalable
}

// error will be IO or timeout
func IsPrime(n *big.Int) (bool, error) {
    if n.Cmp(big2) < 0 {
        return false, nil
    }

    r := new(big.Int)
    r.Sqrt(n)

    fmt.Printf("IsPrime: %v/%v/%v\n", n, r, primes)

    ps := new(Primes)

    for {
        p, err := ps.Next()
        if err != nil {
            return false, err
        }
        fmt.Printf("IsPrime: %v/%v/%v/%v\n", n, r, p, primes)

        if p.Cmp(r) > 0 {
            break
        }
        m := new(big.Int)
        if m.Mod(n, p).Cmp(big0) == 0 {
            return false, nil
        }
    }
    return true, nil
}

func (ps *Primes) Next() (*big.Int, error) {
    //pMutex.Lock() // TODO optimize
    //defer pMutex.Unlock()

    fmt.Printf("Next:%v/%v\n", ps.i, primes)

    if ps.i < len(primes) {
        i := ps.i
        ps.i++
        return newInt(primes[i]), nil
    }

    p := newInt(primes[len(primes)-1])

    for {
        p.Add(p, big2)

        b, err := IsPrime(p)
        if err != nil {
            return nil, err
        }
        if b {
            primes = append(primes, newInt(p))

            ps.i++
            return newInt(p), nil
        }
    }
}

func newInt(i *big.Int) *big.Int {
    bi := new(big.Int)
    bi.Set(i)

    return bi
}
<commit_msg>Modified prime.go.<commit_after>package prime

import (
    "fmt"
    "math/big"
    "sync"

    "github.com/boltdb/bolt"
)

var big0 = big.NewInt(0)
var big2 = big.NewInt(2)
var big3 = big.NewInt(3)

var primes = []*big.Int{big2, big3}
var pMutex = new(sync.Mutex)

// db format
//  "nSuccession": bytes of big.Int
//  "succession": Bucket
//    big.Int: 1
//  "noSuccession": Bucket
//    big.Int: 0,1
var db bolt.DB

type Primes struct {
    i int // TODO more scalable
}

// error will be IO or timeout
func IsPrime(n *big.Int) (bool, error) {
    if n.Cmp(big2) < 0 {
        return false, nil
    }

    r := new(big.Int)
    r.Sqrt(n)

    fmt.Printf("IsPrime: %v/%v/%v\n", n, r, primes)

    ps := new(Primes)

    for {
        p, err := ps.Next()
        if err != nil {
            return false, err
        }
        fmt.Printf("IsPrime: %v/%v/%v/%v\n", n, r, p, primes)

        if p.Cmp(r) > 0 {
            break
        }
        m := new(big.Int)
        if m.Mod(n, p).Cmp(big0) == 0 {
            return false, nil
        }
    }
    return true, nil
}

func (ps *Primes) Next() (*big.Int, error) {
    //pMutex.Lock() // TODO optimize
    //defer pMutex.Unlock()

    fmt.Printf("Next:%v/%v\n", ps.i, primes)

    if ps.i < len(primes) {
        i := ps.i
        ps.i++
        return newInt(primes[i]), nil
    }

    p := newInt(primes[len(primes)-1])

    for {
        p.Add(p, big2)

        b, err := IsPrime(p)
        if err != nil {
            return nil, err
        }
        if b {
            primes = append(primes, newInt(p))

            ps.i++
            return newInt(p), nil
        }
    }
}

func newInt(i *big.Int) *big.Int {
    bi := new(big.Int)
    bi.Set(i)

    return bi
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"github.com/gibheer/pki"
)

const (
	RsaLowerLength = 2048
	RsaUpperLength = 16384
)

var (
	// error messages
	ErrNoPKFound     = errors.New("no private key found")
	ErrNoPUFound     = errors.New("no public key found")
	ErrUnknownFormat = errors.New("key is an unknown format")

	// the possible ecdsa curves allowed to be used
	EcdsaCurves = []int{224, 256, 384, 521}

	// Command to create a private key
	CmdCreatePrivateKey = &Command{
		Use:     "create-private",
		Short:   "create a private key",
		Long:    "Create an ecdsa or rsa key with this command",
		Example: "create-private -type=ecdsa -length=521",
		Run:     create_private_key,
	}
	// private key specific stuff
	FlagPrivateKeyGeneration privateKeyGenerationFlags
)

type (
	// The flags specific to create a private key
	privateKeyGenerationFlags struct {
		Type  string         // type of the private key (rsa, ecdsa)
		Curve elliptic.Curve // curve for ecdsa
		Size  int            // bitsize for rsa
	}
)

// create a new private key
func create_private_key(cmd *Command, args []string) {
	err := checkFlags(checkOutput, checkPrivateKeyGeneration)
	if err != nil {
		crash_with_help(cmd, ErrorFlagInput, "Flags invalid: %s", err)
	}

	var pk pki.Pemmer
	switch FlagPrivateKeyGeneration.Type {
	case "ecdsa":
		pk, err = pki.NewPrivateKeyEcdsa(FlagPrivateKeyGeneration.Curve)
	case "rsa":
		pk, err = pki.NewPrivateKeyRsa(FlagPrivateKeyGeneration.Size)
	default:
		crash_with_help(cmd, ErrorInput, "Unknown private key type '%s'", FlagPrivateKeyGeneration.Type)
	}
	if err != nil {
		crash_with_help(cmd, ErrorProgram, "Error creating private key: %s", err)
	}
	marsh_pem, err := pk.MarshalPem()
	if err != nil {
		crash_with_help(cmd, ErrorProgram, "Error when marshalling to pem: %s", err)
	}
	_, err = marsh_pem.WriteTo(FlagOutput)
	if err != nil {
		crash_with_help(cmd, ErrorProgram, "Error when writing output: %s", err)
	}
}

// This function adds the private key generation flags.
func InitFlagPrivateKeyGeneration(cmd *Command) {
	cmd.Flags().StringVar(&flagContainer.cryptType, "type", "ecdsa", "the type of the private key (ecdsa, rsa)")
	cmd.Flags().IntVar(
		&flagContainer.length,
		"length", 521,
		fmt.Sprintf("%d - %d for rsa; one of %v for ecdsa", RsaLowerLength, RsaUpperLength, EcdsaCurves),
	)
}

// check the private key generation variables and move them to the work space
func checkPrivateKeyGeneration() error {
	pk_type := flagContainer.cryptType
	FlagPrivateKeyGeneration.Type = pk_type
	switch pk_type {
	case "ecdsa":
		switch flagContainer.length {
		case 224:
			FlagPrivateKeyGeneration.Curve = elliptic.P224()
		case 256:
			FlagPrivateKeyGeneration.Curve = elliptic.P256()
		case 384:
			FlagPrivateKeyGeneration.Curve = elliptic.P384()
		case 521:
			FlagPrivateKeyGeneration.Curve = elliptic.P521()
		default:
			return fmt.Errorf("Curve %d unknown!", flagContainer.length)
		}
	case "rsa":
		size := flagContainer.length
		if RsaLowerLength <= size && size <= RsaUpperLength {
			FlagPrivateKeyGeneration.Size = size
		} else {
			return fmt.Errorf("Length of %d is not allowed for rsa!", size)
		}
	default:
		return fmt.Errorf("Type %s is unknown!", pk_type)
	}
	return nil
}

// add the private key option to the requested flags
func InitFlagPrivateKey(cmd *Command) {
	cmd.Flags().StringVar(&flagContainer.privateKeyPath, "private-key", "", "path to the private key (required)")
}

// check the private key flag and load the private key
func checkPrivateKey() error {
	if flagContainer.privateKeyPath == "" {
		return fmt.Errorf("No private key given!")
	}
	// check permissions of private key file
	info, err := os.Stat(flagContainer.privateKeyPath)
	if err != nil {
		return fmt.Errorf("Error reading private key: %s", err)
	}
	if info.Mode().Perm().String()[4:] != "------" {
		return fmt.Errorf("private key file modifyable by others!")
	}

	pk, err := ReadPrivateKeyFile(flagContainer.privateKeyPath)
	if err != nil {
		return fmt.Errorf("Error reading private key: %s", err)
	}
	FlagPrivateKey = pk
	return nil
}

// Read the private key from the path and try to figure out which type of key it
// might be.
func ReadPrivateKeyFile(path string) (pki.PrivateKey, error) {
	raw_pk, err := readSectionFromFile(path, pki.PemLabelEcdsa)
	if err == nil {
		pk, err := pki.LoadPrivateKeyEcdsa(raw_pk)
		if err != nil {
			return nil, err
		}
		return pk, nil
	}
	raw_pk, err = readSectionFromFile(path, pki.PemLabelRsa)
	if err == nil {
		pk, err := pki.LoadPrivateKeyRsa(raw_pk)
		if err != nil {
			return nil, err
		}
		return pk, nil
	}
	return nil, ErrNoPKFound
}

// read the public key and try to figure out what kind of key it might be
func ReadPublicKeyFile(path string) (pki.PublicKey, error) {
	raw_pu, err := readSectionFromFile(path, pki.PemLabelPublic)
	if err != nil {
		return nil, ErrNoPUFound
	}

	var public pki.PublicKey
	public, err = pki.LoadPublicKeyEcdsa(raw_pu)
	if err == nil {
		return public, nil
	}
	public, err = pki.LoadPublicKeyRsa(raw_pu)
	if err == nil {
		return public, nil
	}
	return nil, ErrUnknownFormat
}
<commit_msg>fix imports<commit_after>package main

import (
	"crypto/elliptic"
	"errors"
	"fmt"
	"os"

	"github.com/gibheer/pki"
)

const (
	RsaLowerLength = 2048
	RsaUpperLength = 16384
)

var (
	// error messages
	ErrNoPKFound     = errors.New("no private key found")
	ErrNoPUFound     = errors.New("no public key found")
	ErrUnknownFormat = errors.New("key is an unknown format")

	// the possible ecdsa curves allowed to be used
	EcdsaCurves = []int{224, 256, 384, 521}

	// Command to create a private key
	CmdCreatePrivateKey = &Command{
		Use:     "create-private",
		Short:   "create a private key",
		Long:    "Create an ecdsa or rsa key with this command",
		Example: "create-private -type=ecdsa -length=521",
		Run:     create_private_key,
	}
	// private key specific stuff
	FlagPrivateKeyGeneration privateKeyGenerationFlags
)

type (
	// The flags specific to create a private key
	privateKeyGenerationFlags struct {
		Type  string         // type of the private key (rsa, ecdsa)
		Curve elliptic.Curve // curve for ecdsa
		Size  int            // bitsize for rsa
	}
)

// create a new private key
func create_private_key(cmd *Command, args []string) {
	err := checkFlags(checkOutput, checkPrivateKeyGeneration)
	if err != nil {
		crash_with_help(cmd, ErrorFlagInput, "Flags invalid: %s", err)
	}

	var pk pki.Pemmer
	switch FlagPrivateKeyGeneration.Type {
	case "ecdsa":
		pk, err = pki.NewPrivateKeyEcdsa(FlagPrivateKeyGeneration.Curve)
	case "rsa":
		pk, err = pki.NewPrivateKeyRsa(FlagPrivateKeyGeneration.Size)
	default:
		crash_with_help(cmd, ErrorInput, "Unknown private key type '%s'", FlagPrivateKeyGeneration.Type)
	}
	if err != nil {
		crash_with_help(cmd, ErrorProgram, "Error creating private key: %s", err)
	}
	marsh_pem, err := pk.MarshalPem()
	if err != nil {
		crash_with_help(cmd, ErrorProgram, "Error when marshalling to pem: %s", err)
	}
	_, err = marsh_pem.WriteTo(FlagOutput)
	if err != nil {
		crash_with_help(cmd, ErrorProgram, "Error when writing output: %s", err)
	}
}

// This function adds the private key generation flags.
func InitFlagPrivateKeyGeneration(cmd *Command) {
	cmd.Flags().StringVar(&flagContainer.cryptType, "type", "ecdsa", "the type of the private key (ecdsa, rsa)")
	cmd.Flags().IntVar(
		&flagContainer.length,
		"length", 521,
		fmt.Sprintf("%d - %d for rsa; one of %v for ecdsa", RsaLowerLength, RsaUpperLength, EcdsaCurves),
	)
}

// check the private key generation variables and move them to the work space
func checkPrivateKeyGeneration() error {
	pk_type := flagContainer.cryptType
	FlagPrivateKeyGeneration.Type = pk_type
	switch pk_type {
	case "ecdsa":
		switch flagContainer.length {
		case 224:
			FlagPrivateKeyGeneration.Curve = elliptic.P224()
		case 256:
			FlagPrivateKeyGeneration.Curve = elliptic.P256()
		case 384:
			FlagPrivateKeyGeneration.Curve = elliptic.P384()
		case 521:
			FlagPrivateKeyGeneration.Curve = elliptic.P521()
		default:
			return fmt.Errorf("Curve %d unknown!", flagContainer.length)
		}
	case "rsa":
		size := flagContainer.length
		if RsaLowerLength <= size && size <= RsaUpperLength {
			FlagPrivateKeyGeneration.Size = size
		} else {
			return fmt.Errorf("Length of %d is not allowed for rsa!", size)
		}
	default:
		return fmt.Errorf("Type %s is unknown!", pk_type)
	}
	return nil
}

// add the private key option to the requested flags
func InitFlagPrivateKey(cmd *Command) {
	cmd.Flags().StringVar(&flagContainer.privateKeyPath, "private-key", "", "path to the private key (required)")
}

// check the private key flag and load the private key
func checkPrivateKey() error {
	if flagContainer.privateKeyPath == "" {
		return fmt.Errorf("No private key given!")
	}
	// check permissions of private key file
	info, err := os.Stat(flagContainer.privateKeyPath)
	if err != nil {
		return fmt.Errorf("Error reading private key: %s", err)
	}
	if info.Mode().Perm().String()[4:] != "------" {
		return fmt.Errorf("private key file modifyable by others!")
	}

	pk, err := ReadPrivateKeyFile(flagContainer.privateKeyPath)
	if err != nil {
		return fmt.Errorf("Error reading private key: %s", err)
	}
	FlagPrivateKey = pk
	return nil
}

// Read the private key from the path and try to figure out which type of key it
// might be.
func ReadPrivateKeyFile(path string) (pki.PrivateKey, error) {
	raw_pk, err := readSectionFromFile(path, pki.PemLabelEcdsa)
	if err == nil {
		pk, err := pki.LoadPrivateKeyEcdsa(raw_pk)
		if err != nil {
			return nil, err
		}
		return pk, nil
	}
	raw_pk, err = readSectionFromFile(path, pki.PemLabelRsa)
	if err == nil {
		pk, err := pki.LoadPrivateKeyRsa(raw_pk)
		if err != nil {
			return nil, err
		}
		return pk, nil
	}
	return nil, ErrNoPKFound
}

// read the public key and try to figure out what kind of key it might be
func ReadPublicKeyFile(path string) (pki.PublicKey, error) {
	raw_pu, err := readSectionFromFile(path, pki.PemLabelPublic)
	if err != nil {
		return nil, ErrNoPUFound
	}

	var public pki.PublicKey
	public, err = pki.LoadPublicKeyEcdsa(raw_pu)
	if err == nil {
		return public, nil
	}
	public, err = pki.LoadPublicKeyRsa(raw_pu)
	if err == nil {
		return public, nil
	}
	return nil, ErrUnknownFormat
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Knative Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package generators

import (
	"io"
	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"
	"k8s.io/klog"
)

// reconcilerControllerGenerator produces a file for setting up the reconciler
// with injection.
type reconcilerControllerGenerator struct {
	generator.DefaultGen
	outputPackage  string
	imports        namer.ImportTracker
	typeToGenerate *types.Type

	groupName           string
	clientPkg           string
	schemePkg           string
	informerPackagePath string
}

var _ generator.Generator = (*reconcilerControllerGenerator)(nil)

func (g *reconcilerControllerGenerator) Filter(c *generator.Context, t *types.Type) bool {
	// Only process the type for this generator.
	return t == g.typeToGenerate
}

func (g *reconcilerControllerGenerator) Namers(c *generator.Context) namer.NameSystems {
	return namer.NameSystems{
		"raw": namer.NewRawNamer(g.outputPackage, g.imports),
	}
}

func (g *reconcilerControllerGenerator) Imports(c *generator.Context) (imports []string) {
	imports = append(imports, g.imports.ImportLines()...)
	return
}

func (g *reconcilerControllerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
	sw := generator.NewSnippetWriter(w, c, "{{", "}}")

	klog.V(5).Infof("processing type %v", t)

	m := map[string]interface{}{
		"type":  t,
		"group": g.groupName,
		"controllerImpl": c.Universe.Type(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "Impl",
		}),
		"controllerReconciler": c.Universe.Type(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "Reconciler",
		}),
		"controllerNewImpl": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "NewImpl",
		}),
		"loggingFromContext": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/logging",
			Name:    "FromContext",
		}),
		"ptrString": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/ptr",
			Name:    "String",
		}),
		"corev1EventSource": c.Universe.Function(types.Name{
			Package: "k8s.io/api/core/v1",
			Name:    "EventSource",
		}),
		"clientGet": c.Universe.Function(types.Name{
			Package: g.clientPkg,
			Name:    "Get",
		}),
		"informerGet": c.Universe.Function(types.Name{
			Package: g.informerPackagePath,
			Name:    "Get",
		}),
		"schemeScheme": c.Universe.Function(types.Name{
			Package: "k8s.io/client-go/kubernetes/scheme",
			Name:    "Scheme",
		}),
		"schemeAddToScheme": c.Universe.Function(types.Name{
			Package: g.schemePkg,
			Name:    "AddToScheme",
		}),
		"kubeclientGet": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/client/injection/kube/client",
			Name:    "Get",
		}),
		"typedcorev1EventSinkImpl": c.Universe.Function(types.Name{
			Package: "k8s.io/client-go/kubernetes/typed/core/v1",
			Name:    "EventSinkImpl",
		}),
		"recordNewBroadcaster": c.Universe.Function(types.Name{
			Package: "k8s.io/client-go/tools/record",
			Name:    "NewBroadcaster",
		}),
		"watchInterface": c.Universe.Type(types.Name{
			Package: "k8s.io/apimachinery/pkg/watch",
			Name:    "Interface",
		}),
		"controllerGetEventRecorder": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "GetEventRecorder",
		}),
	}

	sw.Do(reconcilerControllerNewImpl, m)

	return sw.Error()
}

var reconcilerControllerNewImpl = `
const (
	defaultControllerAgentName = "{{.type|lowercaseSingular}}-controller"
	defaultFinalizerName       = "{{.type|allLowercasePlural}}.{{.group}}"
	defaultQueueName           = "{{.type|allLowercasePlural}}"
)

// NewImpl returns a {{.controllerImpl|raw}} that handles queuing and feeding work from
// the queue through an implementation of {{.controllerReconciler|raw}}, delegating to
// the provided Interface and optional Finalizer methods.
func NewImpl(ctx context.Context, r Interface) *{{.controllerImpl|raw}} {
	logger := {{.loggingFromContext|raw}}(ctx)
	{{.type|lowercaseSingular}}Informer := {{.informerGet|raw}}(ctx)

	recorder := {{.controllerGetEventRecorder|raw}}(ctx)
	if recorder == nil {
		// Create event broadcaster
		logger.Debug("Creating event broadcaster")
		eventBroadcaster := {{.recordNewBroadcaster|raw}}()
		watches := []{{.watchInterface|raw}}{
			eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof),
			eventBroadcaster.StartRecordingToSink(
				&{{.typedcorev1EventSinkImpl|raw}}{Interface: {{.kubeclientGet|raw}}(ctx).CoreV1().Events("")}),
		}
		recorder = eventBroadcaster.NewRecorder({{.schemeScheme|raw}}, {{.corev1EventSource|raw}}{Component: defaultControllerAgentName})
		go func() {
			<-ctx.Done()
			for _, w := range watches {
				w.Stop()
			}
		}()
	}

	rec := &reconcilerImpl{
		Client:  {{.clientGet|raw}}(ctx),
		Lister:  {{.type|lowercaseSingular}}Informer.Lister(),
		Recorder: recorder,
		reconciler:    r,
	}
	return {{.controllerNewImpl|raw}}(rec, logger, defaultQueueName)
}

func init() {
	{{.schemeAddToScheme|raw}}({{.schemeScheme|raw}})
}
`
<commit_msg>golang format tools (#1072)<commit_after>/*
Copyright 2020 The Knative Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package generators

import (
	"io"

	"k8s.io/gengo/generator"
	"k8s.io/gengo/namer"
	"k8s.io/gengo/types"
	"k8s.io/klog"
)

// reconcilerControllerGenerator produces a file for setting up the reconciler
// with injection.
type reconcilerControllerGenerator struct {
	generator.DefaultGen
	outputPackage  string
	imports        namer.ImportTracker
	typeToGenerate *types.Type

	groupName           string
	clientPkg           string
	schemePkg           string
	informerPackagePath string
}

var _ generator.Generator = (*reconcilerControllerGenerator)(nil)

func (g *reconcilerControllerGenerator) Filter(c *generator.Context, t *types.Type) bool {
	// Only process the type for this generator.
	return t == g.typeToGenerate
}

func (g *reconcilerControllerGenerator) Namers(c *generator.Context) namer.NameSystems {
	return namer.NameSystems{
		"raw": namer.NewRawNamer(g.outputPackage, g.imports),
	}
}

func (g *reconcilerControllerGenerator) Imports(c *generator.Context) (imports []string) {
	imports = append(imports, g.imports.ImportLines()...)
	return
}

func (g *reconcilerControllerGenerator) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {
	sw := generator.NewSnippetWriter(w, c, "{{", "}}")

	klog.V(5).Infof("processing type %v", t)

	m := map[string]interface{}{
		"type":  t,
		"group": g.groupName,
		"controllerImpl": c.Universe.Type(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "Impl",
		}),
		"controllerReconciler": c.Universe.Type(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "Reconciler",
		}),
		"controllerNewImpl": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "NewImpl",
		}),
		"loggingFromContext": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/logging",
			Name:    "FromContext",
		}),
		"ptrString": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/ptr",
			Name:    "String",
		}),
		"corev1EventSource": c.Universe.Function(types.Name{
			Package: "k8s.io/api/core/v1",
			Name:    "EventSource",
		}),
		"clientGet": c.Universe.Function(types.Name{
			Package: g.clientPkg,
			Name:    "Get",
		}),
		"informerGet": c.Universe.Function(types.Name{
			Package: g.informerPackagePath,
			Name:    "Get",
		}),
		"schemeScheme": c.Universe.Function(types.Name{
			Package: "k8s.io/client-go/kubernetes/scheme",
			Name:    "Scheme",
		}),
		"schemeAddToScheme": c.Universe.Function(types.Name{
			Package: g.schemePkg,
			Name:    "AddToScheme",
		}),
		"kubeclientGet": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/client/injection/kube/client",
			Name:    "Get",
		}),
		"typedcorev1EventSinkImpl": c.Universe.Function(types.Name{
			Package: "k8s.io/client-go/kubernetes/typed/core/v1",
			Name:    "EventSinkImpl",
		}),
		"recordNewBroadcaster": c.Universe.Function(types.Name{
			Package: "k8s.io/client-go/tools/record",
			Name:    "NewBroadcaster",
		}),
		"watchInterface": c.Universe.Type(types.Name{
			Package: "k8s.io/apimachinery/pkg/watch",
			Name:    "Interface",
		}),
		"controllerGetEventRecorder": c.Universe.Function(types.Name{
			Package: "knative.dev/pkg/controller",
			Name:    "GetEventRecorder",
		}),
	}

	sw.Do(reconcilerControllerNewImpl, m)

	return sw.Error()
}

var reconcilerControllerNewImpl = `
const (
	defaultControllerAgentName = "{{.type|lowercaseSingular}}-controller"
	defaultFinalizerName       = "{{.type|allLowercasePlural}}.{{.group}}"
	defaultQueueName           = "{{.type|allLowercasePlural}}"
)

// NewImpl returns a {{.controllerImpl|raw}} that handles queuing and feeding work from
// the queue through an implementation of {{.controllerReconciler|raw}}, delegating to
// the provided Interface and optional Finalizer methods.
func NewImpl(ctx context.Context, r Interface) *{{.controllerImpl|raw}} {
	logger := {{.loggingFromContext|raw}}(ctx)
	{{.type|lowercaseSingular}}Informer := {{.informerGet|raw}}(ctx)

	recorder := {{.controllerGetEventRecorder|raw}}(ctx)
	if recorder == nil {
		// Create event broadcaster
		logger.Debug("Creating event broadcaster")
		eventBroadcaster := {{.recordNewBroadcaster|raw}}()
		watches := []{{.watchInterface|raw}}{
			eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof),
			eventBroadcaster.StartRecordingToSink(
				&{{.typedcorev1EventSinkImpl|raw}}{Interface: {{.kubeclientGet|raw}}(ctx).CoreV1().Events("")}),
		}
		recorder = eventBroadcaster.NewRecorder({{.schemeScheme|raw}}, {{.corev1EventSource|raw}}{Component: defaultControllerAgentName})
		go func() {
			<-ctx.Done()
			for _, w := range watches {
				w.Stop()
			}
		}()
	}

	rec := &reconcilerImpl{
		Client:  {{.clientGet|raw}}(ctx),
		Lister:  {{.type|lowercaseSingular}}Informer.Lister(),
		Recorder: recorder,
		reconciler:    r,
	}
	return {{.controllerNewImpl|raw}}(rec, logger, defaultQueueName)
}

func init() {
	{{.schemeAddToScheme|raw}}({{.schemeScheme|raw}})
}
`
<|endoftext|>


<commit_before>package invdapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"github.com/Invoiced/invoiced-go/invdendpoint"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"strings"
)

const requestURL = "https://api.invoiced.com"
const devRequestURL = "https://api.sandbox.invoiced.com"
const requestType = "application/json"
const InvoicedTokenString = "invoicedToken"

const version = "0.1"

func Version() string {
	return version
}

type Connection struct {
	key             string
	itemsPerRequest int
	client          *http.Client
	url             string
}

type InvoicedToken struct {
	Key string `json:"invoicedApiKey"`
}

func NewConnection(key string, devMode bool) *Connection {
	c := new(Connection)
	c.key = key
	c.client = new(http.Client)
	if devMode {
		c.url = devRequestURL
	} else {
		c.url = requestURL
	}

	return c
}

func checkStatusForError(status int, r io.Reader) error {
	if status < 400 {
		return nil
	}

	body, err := ioutil.ReadAll(r)
	if err != nil {
		panic(err)
	}

	apiError := new(APIError)

	log.Println("json body => ", string(body))
	err = json.Unmarshal(body, apiError)

	if err != nil {
		apiError.Type = string(body)

	}

	return errors.New(apiError.Error())

}

func pushDataIntoStruct(endPointData interface{}, respBody io.Reader) {

	body, err := ioutil.ReadAll(respBody)

	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(body, endPointData)

	if err != nil {
		panic(err)
	}

}

func parseURLLinksFromString(s string) map[string]string {

	urlAndLinkMap := make(map[string]string)

	rawURLLinksAndRelations := strings.Split(s, ",")

	for _, rawURLLinkRelation := range rawURLLinksAndRelations {
		parsedRawURLAndRelation := strings.Split(rawURLLinkRelation, ";")
		url := parseRawURL(parsedRawURLAndRelation[0])
		relation := parseRawRelation(parsedRawURLAndRelation[1])

		urlAndLinkMap[relation] = url
	}

	return urlAndLinkMap
}

func parseRawRelation(s string) string {
	//parse rel="last" => last

	first := strings.Index(s, "\"")
	last := strings.LastIndex(s, "\"")

	trimmed := s[first+1 : last]

	trimmed = strings.TrimSpace(trimmed)

	return trimmed

}

func parseRawURL(s string) string {
	//<https://api.invoiced.com/invoices?page=1>

	trimmed := strings.Trim(s, " < ")

	trimmed = strings.Trim(trimmed, " > ")

	trimmed = strings.TrimSpace(trimmed)

	return trimmed

}

func addFilterSortToEndPoint(endpoint string, filter *invdendpoint.Filter, sort *invdendpoint.Sort) string {

	emptyFilter := true
	emptySort := true

	if filter != nil && filter.String() != "" {
		emptyFilter = false
	}

	if sort != nil && sort.String() != "" {
		emptySort = false
	}

	if !emptyFilter && !emptySort {
		return endpoint + "?" + filter.String() + "&" + sort.String()
	} else if !emptyFilter && emptySort {
		return endpoint + "?" + filter.String()
	} else if emptyFilter && !emptySort {
		return endpoint + "?" + sort.String()
	}

	return endpoint

}

func makeEndPointSingular(endpoint string, id int64) string {
	return endpoint + "/" + strconv.FormatInt(id, 10)
}

func (c *Connection) makeEndPointURL(endPoint string) string {

	return c.url + endPoint
}

func (c *Connection) setItemsPerRequest(items int) {
	c.itemsPerRequest = items
}

func (c *Connection) get(endPoint string) *http.Response {

	req, err := http.NewRequest("GET", endPoint, nil)
	req.SetBasicAuth(c.key, "")

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) post(endPoint string, body io.Reader) *http.Response {

	req, err := http.NewRequest("POST", endPoint, body)
	req.SetBasicAuth(c.key, "")
	req.Header.Set("Content-Type", requestType)

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) patch(endPoint string, body io.Reader) *http.Response {

	req, err := http.NewRequest("PATCH", endPoint, body)
	req.SetBasicAuth(c.key, "")
	req.Header.Set("Content-Type", requestType)

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) deleteRequest(endPoint string) *http.Response {

	req, err := http.NewRequest("DELETE", endPoint, nil)
	req.SetBasicAuth(c.key, "")
	req.Header.Set("Content-Type", requestType)

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) create(endPoint string, requestData interface{}, responseData interface{}) error {

	b, err := json.Marshal(requestData)

	if err != nil {
		panic(err)
	}

	body := bytes.NewBuffer(b)

	resp := c.post(endPoint, body)

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return apiError
	}

	pushDataIntoStruct(responseData, resp.Body)

	return nil

}

func (c *Connection) delete(endPoint string) error {

	resp := c.deleteRequest(endPoint)

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return apiError
	}

	return nil

}

func (c *Connection) update(endPoint string, requestData interface{}, responseData interface{}) error {

	b, err := json.Marshal(requestData)

	if err != nil {
		panic(err)
	}

	body := bytes.NewBuffer(b)

	resp := c.patch(endPoint, body)

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return apiError
	}

	pushDataIntoStruct(responseData, resp.Body)

	return nil

}

func (c *Connection) count(endPoint string) (int64, error) {
	resp := c.get(endPoint)

	defer resp.Body.Close()

	apiErr := checkStatusForError(resp.StatusCode, resp.Body)

	if apiErr != nil {
		return 0, apiErr
	}

	s := resp.Header.Get("X-Total-Count")

	i, err := strconv.ParseInt(s, 10, 64)

	if err != nil {
		panic(err)
	}

	return i, nil

}

func (c *Connection) retrieveDataFromAPI(endPoint string, endPointData interface{}) (string, error) {

	nextURL := ""

	resp := c.get(endPoint)

	defer resp.Body.Close()

	link := resp.Header.Get("Link")

	if link != "" {
		nextMap := parseURLLinksFromString(link)

		if nextMap["self"] != nextMap["next"] {
			nextURL = nextMap["next"]
		}
	}

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return "", apiError
	}

	pushDataIntoStruct(endPointData, resp.Body)

	return nextURL, nil

}
<commit_msg>more debugging<commit_after>package invdapi

import (
	"bytes"
	"encoding/json"
	"errors"
	"github.com/Invoiced/invoiced-go/invdendpoint"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strconv"
	"strings"
)

const requestURL = "https://api.invoiced.com"
const devRequestURL = "https://api.sandbox.invoiced.com"
const requestType = "application/json"
const InvoicedTokenString = "invoicedToken"

const version = "0.1"

func Version() string {
	return version
}

type Connection struct {
	key             string
	itemsPerRequest int
	client          *http.Client
	url             string
}

type InvoicedToken struct {
	Key string `json:"invoicedApiKey"`
}

func NewConnection(key string, devMode bool) *Connection {
	c := new(Connection)
	c.key = key
	c.client = new(http.Client)
	if devMode {
		c.url = devRequestURL
	} else {
		c.url = requestURL
	}

	return c
}

func checkStatusForError(status int, r io.Reader) error {
	if status < 400 {
		return nil
	}

	body, err := ioutil.ReadAll(r)
	if err != nil {
		panic(err)
	}

	apiError := new(APIError)

	log.Println("json body => ", string(body))
	err = json.Unmarshal(body, apiError)

	if err != nil {
		apiError.Type = string(body)

	}

	return errors.New(apiError.Error())

}

func pushDataIntoStruct(endPointData interface{}, respBody io.Reader) {

	body, err := ioutil.ReadAll(respBody)

	if err != nil {
		panic(err)
	}

	err = json.Unmarshal(body, endPointData)

	if err != nil {
		log.Println("dump json => ", string(body))
		panic(err)
	}

}

func parseURLLinksFromString(s string) map[string]string {

	urlAndLinkMap := make(map[string]string)

	rawURLLinksAndRelations := strings.Split(s, ",")

	for _, rawURLLinkRelation := range rawURLLinksAndRelations {
		parsedRawURLAndRelation := strings.Split(rawURLLinkRelation, ";")
		url := parseRawURL(parsedRawURLAndRelation[0])
		relation := parseRawRelation(parsedRawURLAndRelation[1])

		urlAndLinkMap[relation] = url
	}

	return urlAndLinkMap
}

func parseRawRelation(s string) string {
	//parse rel="last" => last

	first := strings.Index(s, "\"")
	last := strings.LastIndex(s, "\"")

	trimmed := s[first+1 : last]

	trimmed = strings.TrimSpace(trimmed)

	return trimmed

}

func parseRawURL(s string) string {
	//<https://api.invoiced.com/invoices?page=1>

	trimmed := strings.Trim(s, " < ")

	trimmed = strings.Trim(trimmed, " > ")

	trimmed = strings.TrimSpace(trimmed)

	return trimmed

}

func addFilterSortToEndPoint(endpoint string, filter *invdendpoint.Filter, sort *invdendpoint.Sort) string {

	emptyFilter := true
	emptySort := true

	if filter != nil && filter.String() != "" {
		emptyFilter = false
	}

	if sort != nil && sort.String() != "" {
		emptySort = false
	}

	if !emptyFilter && !emptySort {
		return endpoint + "?" + filter.String() + "&" + sort.String()
	} else if !emptyFilter && emptySort {
		return endpoint + "?" + filter.String()
	} else if emptyFilter && !emptySort {
		return endpoint + "?" + sort.String()
	}

	return endpoint

}

func makeEndPointSingular(endpoint string, id int64) string {
	return endpoint + "/" + strconv.FormatInt(id, 10)
}

func (c *Connection) makeEndPointURL(endPoint string) string {

	return c.url + endPoint
}

func (c *Connection) setItemsPerRequest(items int) {
	c.itemsPerRequest = items
}

func (c *Connection) get(endPoint string) *http.Response {

	req, err := http.NewRequest("GET", endPoint, nil)
	req.SetBasicAuth(c.key, "")

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) post(endPoint string, body io.Reader) *http.Response {

	req, err := http.NewRequest("POST", endPoint, body)
	req.SetBasicAuth(c.key, "")
	req.Header.Set("Content-Type", requestType)

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) patch(endPoint string, body io.Reader) *http.Response {

	req, err := http.NewRequest("PATCH", endPoint, body)
	req.SetBasicAuth(c.key, "")
	req.Header.Set("Content-Type", requestType)

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) deleteRequest(endPoint string) *http.Response {

	req, err := http.NewRequest("DELETE", endPoint, nil)
	req.SetBasicAuth(c.key, "")
	req.Header.Set("Content-Type", requestType)

	resp, err := c.client.Do(req)

	if err != nil {
		panic(err)
	}

	return resp

}

func (c *Connection) create(endPoint string, requestData interface{}, responseData interface{}) error {

	b, err := json.Marshal(requestData)

	if err != nil {
		panic(err)
	}

	body := bytes.NewBuffer(b)

	resp := c.post(endPoint, body)

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return apiError
	}

	pushDataIntoStruct(responseData, resp.Body)

	return nil

}

func (c *Connection) delete(endPoint string) error {

	resp := c.deleteRequest(endPoint)

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return apiError
	}

	return nil

}

func (c *Connection) update(endPoint string, requestData interface{}, responseData interface{}) error {

	b, err := json.Marshal(requestData)

	if err != nil {
		panic(err)
	}

	body := bytes.NewBuffer(b)

	resp := c.patch(endPoint, body)

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return apiError
	}

	pushDataIntoStruct(responseData, resp.Body)

	return nil

}

func (c *Connection) count(endPoint string) (int64, error) {
	resp := c.get(endPoint)

	defer resp.Body.Close()

	apiErr := checkStatusForError(resp.StatusCode, resp.Body)

	if apiErr != nil {
		return 0, apiErr
	}

	s := resp.Header.Get("X-Total-Count")

	i, err := strconv.ParseInt(s, 10, 64)

	if err != nil {
		panic(err)
	}

	return i, nil

}

func (c *Connection) retrieveDataFromAPI(endPoint string, endPointData interface{}) (string, error) {

	nextURL := ""

	resp := c.get(endPoint)

	defer resp.Body.Close()

	link := resp.Header.Get("Link")

	if link != "" {
		nextMap := parseURLLinksFromString(link)

		if nextMap["self"] != nextMap["next"] {
			nextURL = nextMap["next"]
		}
	}

	apiError := checkStatusForError(resp.StatusCode, resp.Body)

	if apiError != nil {
		return "", apiError
	}

	pushDataIntoStruct(endPointData, resp.Body)

	return nextURL, nil

}
<|endoftext|>