<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/prometheus/client_golang/prometheus"
)

const (
	proto         = "tcp"
	retryInterval = 1
)

var (
	listeningAddress    = flag.String("listeningAddress", ":8080", "Address on which to expose Prometheus metrics.")
	muninAddress        = flag.String("muninAddress", "localhost:4949", "munin-node address.")
	muninScrapeInterval = flag.Int("muninScrapeInterval", 60, "Interval in seconds between scrapes.")
	globalConn          net.Conn
	hostname            string
	graphs              []string
	gaugePerMetric      map[string]*prometheus.GaugeVec
	counterPerMetric     map[string]*prometheus.CounterVec
	muninBanner         *regexp.Regexp
)

func init() {
	flag.Parse()
	var err error
	gaugePerMetric = map[string]*prometheus.GaugeVec{}
	counterPerMetric = map[string]*prometheus.CounterVec{}
	muninBanner = regexp.MustCompile(`# munin node at (.*)`)

	err = connect()
	if err != nil {
		log.Fatalf("Could not connect to %s: %s", *muninAddress, err)
	}
}

func serveStatus() {
	http.Handle("/metrics", prometheus.Handler())
	http.ListenAndServe(*listeningAddress, nil)
}

func connect() (err error) {
	log.Printf("Connecting...")
	globalConn, err = net.Dial(proto, *muninAddress)
	if err != nil {
		return
	}
	log.Printf("connected!")

	reader := bufio.NewReader(globalConn)
	head, err := reader.ReadString('\n')
	if err != nil {
		return
	}

	matches := muninBanner.FindStringSubmatch(head)
	if len(matches) != 2 { // expect: # munin node at <hostname>
		return fmt.Errorf("Unexpected line: %s", head)
	}
	hostname = matches[1]
	log.Printf("Found hostname: %s", hostname)
	return
}

func muninCommand(cmd string) (reader *bufio.Reader, err error) {
	reader = bufio.NewReader(globalConn)

	fmt.Fprintf(globalConn, cmd+"\n")

	_, err = reader.Peek(1)
	switch err {
	case io.EOF:
		log.Printf("not connected anymore, closing connection")
		globalConn.Close()
		for {
			err = connect()
			if err == nil {
				break
			}
			log.Printf("Couldn't reconnect: %s", err)
			time.Sleep(retryInterval * time.Second)
		}

		return muninCommand(cmd)
	case nil: //no error
		break
	default:
		log.Fatalf("Unexpected error: %s", err)
	}

	return
}

func muninList() (items []string, err error) {
	munin, err := muninCommand("list")
	if err != nil {
		log.Printf("couldn't get list")
		return
	}

	response, err := munin.ReadString('\n') // we are only interested in the first line
	if err != nil {
		log.Printf("couldn't read response")
		return
	}

	if response[0] == '#' { // # not expected here
		err = fmt.Errorf("Error getting items: %s", response)
		return
	}
	items = strings.Fields(strings.TrimRight(response, "\n"))
	return
}

func muninConfig(name string) (config map[string]map[string]string, graphConfig map[string]string, err error) {
	graphConfig = make(map[string]string)
	config = make(map[string]map[string]string)

	resp, err := muninCommand("config " + name)
	if err != nil {
		log.Printf("couldn't get config for %s", name)
		return
	}

	for {
		line, err := resp.ReadString('\n')
		if err == io.EOF {
			log.Fatalf("unexpected EOF, retrying")
			return muninConfig(name)
		}
		if err != nil {
			return nil, nil, err
		}
		if line == ".\n" { // munin end marker
			break
		}
		if line[0] == '#' { // here it's just a comment, so ignore it
			continue
		}
		parts := strings.Fields(line)
		if len(parts) < 2 {
			return nil, nil, fmt.Errorf("Line unexpected: %s", line)
		}
		key, value := parts[0], strings.TrimRight(strings.Join(parts[1:], " "), "\n")

		keyParts := strings.Split(key, ".")
		if len(keyParts) > 1 { // it's a metric config (metric.label etc)
			if _, ok := config[keyParts[0]]; !ok { //FIXME: is there no better way?
				config[keyParts[0]] = make(map[string]string)
			}
			config[keyParts[0]][keyParts[1]] = value
		} else {
			graphConfig[keyParts[0]] = value
		}
	}
	return
}

func registerMetrics() (err error) {
	items, err := muninList()
	if err != nil {
		return
	}

	for _, name := range items {
		graphs = append(graphs, name)
		configs, graphConfig, err := muninConfig(name)
		if err != nil {
			return err
		}

		for metric, config := range configs {
			metricName := strings.Replace(name + "_" + metric, "-","_",-1)
			desc := graphConfig["graph_title"] + ": " + config["label"]
			if config["info"] != "" {
				desc = desc + ", " + config["info"]
			}
			muninType := strings.ToLower(config["type"])
			// muninType can be empty and defaults to gauge
			if muninType == "counter" || muninType == "derive" {
	                        gv := prometheus.NewCounterVec(
        	                        prometheus.CounterOpts{
                	                        Name: metricName,
                        	                Help: desc,
						ConstLabels: prometheus.Labels{"type":muninType},
                                	},
                                	[]string{"hostname","graphname","muninlabel"},
                        	)
				log.Printf("Registered counter %s: %s", metricName, desc)
                        	counterPerMetric[metricName] = gv
                        	prometheus.Register(gv)

			} else {
                        	gv := prometheus.NewGaugeVec(
                                	prometheus.GaugeOpts{
                                        	Name: metricName,
	                                        Help: desc,
						ConstLabels: prometheus.Labels{"type":"gauge"},
                	                },
                        	        []string{"hostname","graphname","muninlabel"},
                        	)
				log.Printf("Registered gauge %s: %s", metricName, desc)
        	                gaugePerMetric[metricName] = gv
                	        prometheus.Register(gv)
			}
		}
	}
	return nil
}

func fetchMetrics() (err error) {
	for _, graph := range graphs {
		munin, err := muninCommand("fetch " + graph)
		if err != nil {
			return err
		}

		for {
			line, err := munin.ReadString('\n')
			line = strings.TrimRight(line, "\n")
			if err == io.EOF {
				log.Fatalf("unexpected EOF, retrying")
				return fetchMetrics()
			}
			if err != nil {
				return err
			}
			if len(line) == 1 && line[0] == '.' {
				log.Printf("End of list")
				break
			}

			parts := strings.Fields(line)
			if len(parts) != 2 {
				log.Printf("unexpected line: %s", line)
				continue
			}
			key, valueString := strings.Split(parts[0], ".")[0], parts[1]
			value, err := strconv.ParseFloat(valueString, 64)
			if err != nil {
				log.Printf("Couldn't parse value in line %s, malformed?", line)
				continue
			}
			name := strings.Replace(graph + "_" + key, "-","_",-1)
			log.Printf("%s: %f\n", name, value)
			_, isGauge := gaugePerMetric[name]
			if isGauge {
	                        gaugePerMetric[name].WithLabelValues(hostname, graph, key).Set(value)
			} else {
				counterPerMetric[name].WithLabelValues(hostname, graph, key).Set(value)
			}
		}
	}
	return
}

func main() {
	flag.Parse()
	err := registerMetrics()
	if err != nil {
		log.Fatalf("Could not register metrics: %s", err)
	}

	go serveStatus()

	func() {
		for {
			log.Printf("Scraping")
			err := fetchMetrics()
			if err != nil {
				log.Printf("Error occured when trying to fetch metrics: %s", err)
			}
			time.Sleep(time.Duration(*muninScrapeInterval) * time.Second)
		}
	}()
}
<commit_msg>Use Add() instead of Set() on a counter<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"net/http"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/prometheus/client_golang/prometheus"
)

const (
	proto         = "tcp"
	retryInterval = 1
)

var (
	listeningAddress    = flag.String("listeningAddress", ":8080", "Address on which to expose Prometheus metrics.")
	muninAddress        = flag.String("muninAddress", "localhost:4949", "munin-node address.")
	muninScrapeInterval = flag.Int("muninScrapeInterval", 60, "Interval in seconds between scrapes.")
	globalConn          net.Conn
	hostname            string
	graphs              []string
	gaugePerMetric      map[string]*prometheus.GaugeVec
	counterPerMetric     map[string]*prometheus.CounterVec
	muninBanner         *regexp.Regexp
)

func init() {
	flag.Parse()
	var err error
	gaugePerMetric = map[string]*prometheus.GaugeVec{}
	counterPerMetric = map[string]*prometheus.CounterVec{}
	muninBanner = regexp.MustCompile(`# munin node at (.*)`)

	err = connect()
	if err != nil {
		log.Fatalf("Could not connect to %s: %s", *muninAddress, err)
	}
}

func serveStatus() {
	http.Handle("/metrics", prometheus.Handler())
	http.ListenAndServe(*listeningAddress, nil)
}

func connect() (err error) {
	log.Printf("Connecting...")
	globalConn, err = net.Dial(proto, *muninAddress)
	if err != nil {
		return
	}
	log.Printf("connected!")

	reader := bufio.NewReader(globalConn)
	head, err := reader.ReadString('\n')
	if err != nil {
		return
	}

	matches := muninBanner.FindStringSubmatch(head)
	if len(matches) != 2 { // expect: # munin node at <hostname>
		return fmt.Errorf("Unexpected line: %s", head)
	}
	hostname = matches[1]
	log.Printf("Found hostname: %s", hostname)
	return
}

func muninCommand(cmd string) (reader *bufio.Reader, err error) {
	reader = bufio.NewReader(globalConn)

	fmt.Fprintf(globalConn, cmd+"\n")

	_, err = reader.Peek(1)
	switch err {
	case io.EOF:
		log.Printf("not connected anymore, closing connection")
		globalConn.Close()
		for {
			err = connect()
			if err == nil {
				break
			}
			log.Printf("Couldn't reconnect: %s", err)
			time.Sleep(retryInterval * time.Second)
		}

		return muninCommand(cmd)
	case nil: //no error
		break
	default:
		log.Fatalf("Unexpected error: %s", err)
	}

	return
}

func muninList() (items []string, err error) {
	munin, err := muninCommand("list")
	if err != nil {
		log.Printf("couldn't get list")
		return
	}

	response, err := munin.ReadString('\n') // we are only interested in the first line
	if err != nil {
		log.Printf("couldn't read response")
		return
	}

	if response[0] == '#' { // # not expected here
		err = fmt.Errorf("Error getting items: %s", response)
		return
	}
	items = strings.Fields(strings.TrimRight(response, "\n"))
	return
}

func muninConfig(name string) (config map[string]map[string]string, graphConfig map[string]string, err error) {
	graphConfig = make(map[string]string)
	config = make(map[string]map[string]string)

	resp, err := muninCommand("config " + name)
	if err != nil {
		log.Printf("couldn't get config for %s", name)
		return
	}

	for {
		line, err := resp.ReadString('\n')
		if err == io.EOF {
			log.Fatalf("unexpected EOF, retrying")
			return muninConfig(name)
		}
		if err != nil {
			return nil, nil, err
		}
		if line == ".\n" { // munin end marker
			break
		}
		if line[0] == '#' { // here it's just a comment, so ignore it
			continue
		}
		parts := strings.Fields(line)
		if len(parts) < 2 {
			return nil, nil, fmt.Errorf("Line unexpected: %s", line)
		}
		key, value := parts[0], strings.TrimRight(strings.Join(parts[1:], " "), "\n")

		keyParts := strings.Split(key, ".")
		if len(keyParts) > 1 { // it's a metric config (metric.label etc)
			if _, ok := config[keyParts[0]]; !ok { //FIXME: is there no better way?
				config[keyParts[0]] = make(map[string]string)
			}
			config[keyParts[0]][keyParts[1]] = value
		} else {
			graphConfig[keyParts[0]] = value
		}
	}
	return
}

func registerMetrics() (err error) {
	items, err := muninList()
	if err != nil {
		return
	}

	for _, name := range items {
		graphs = append(graphs, name)
		configs, graphConfig, err := muninConfig(name)
		if err != nil {
			return err
		}

		for metric, config := range configs {
			metricName := strings.Replace(name + "_" + metric, "-","_",-1)
			desc := graphConfig["graph_title"] + ": " + config["label"]
			if config["info"] != "" {
				desc = desc + ", " + config["info"]
			}
			muninType := strings.ToLower(config["type"])
			// muninType can be empty and defaults to gauge
			if muninType == "counter" || muninType == "derive" {
	                        gv := prometheus.NewCounterVec(
        	                        prometheus.CounterOpts{
                	                        Name: metricName,
                        	                Help: desc,
						ConstLabels: prometheus.Labels{"type":muninType},
                                	},
                                	[]string{"hostname","graphname","muninlabel"},
                        	)
				log.Printf("Registered counter %s: %s", metricName, desc)
                        	counterPerMetric[metricName] = gv
                        	prometheus.Register(gv)

			} else {
                        	gv := prometheus.NewGaugeVec(
                                	prometheus.GaugeOpts{
                                        	Name: metricName,
	                                        Help: desc,
						ConstLabels: prometheus.Labels{"type":"gauge"},
                	                },
                        	        []string{"hostname","graphname","muninlabel"},
                        	)
				log.Printf("Registered gauge %s: %s", metricName, desc)
        	                gaugePerMetric[metricName] = gv
                	        prometheus.Register(gv)
			}
		}
	}
	return nil
}

func fetchMetrics() (err error) {
	for _, graph := range graphs {
		munin, err := muninCommand("fetch " + graph)
		if err != nil {
			return err
		}

		for {
			line, err := munin.ReadString('\n')
			line = strings.TrimRight(line, "\n")
			if err == io.EOF {
				log.Fatalf("unexpected EOF, retrying")
				return fetchMetrics()
			}
			if err != nil {
				return err
			}
			if len(line) == 1 && line[0] == '.' {
				log.Printf("End of list")
				break
			}

			parts := strings.Fields(line)
			if len(parts) != 2 {
				log.Printf("unexpected line: %s", line)
				continue
			}
			key, valueString := strings.Split(parts[0], ".")[0], parts[1]
			value, err := strconv.ParseFloat(valueString, 64)
			if err != nil {
				log.Printf("Couldn't parse value in line %s, malformed?", line)
				continue
			}
			name := strings.Replace(graph + "_" + key, "-","_",-1)
			log.Printf("%s: %f\n", name, value)
			_, isGauge := gaugePerMetric[name]
			if isGauge {
	                        gaugePerMetric[name].WithLabelValues(hostname, graph, key).Set(value)
			} else {
				counterPerMetric[name].WithLabelValues(hostname, graph, key).Add(value)
			}
		}
	}
	return
}

func main() {
	flag.Parse()
	err := registerMetrics()
	if err != nil {
		log.Fatalf("Could not register metrics: %s", err)
	}

	go serveStatus()

	func() {
		for {
			log.Printf("Scraping")
			err := fetchMetrics()
			if err != nil {
				log.Printf("Error occured when trying to fetch metrics: %s", err)
			}
			time.Sleep(time.Duration(*muninScrapeInterval) * time.Second)
		}
	}()
}
<|endoftext|>


<commit_before>// +build all integration

package gocql

import (
	"sync/atomic"

	"testing"
)

func BenchmarkConnStress(b *testing.B) {
	const workers = 16

	cluster := createCluster()
	cluster.NumConns = 1
	cluster.NumStreams = workers
	session := createSessionFromCluster(cluster, b)
	defer session.Close()

	if err := createTable(session, "CREATE TABLE IF NOT EXISTS conn_stress (id int primary key)"); err != nil {
		b.Fatal(err)
	}

	var seed uint64
	writer := func(pb *testing.PB) {
		seed := atomic.AddUint64(&seed, 1)
		var i uint64 = 0
		for pb.Next() {
			if err := session.Query("insert into conn_stress (id) values (?)", i*seed).Exec(); err != nil {
				b.Error(err)
				return
			}
			i++
		}
	}

	b.SetParallelism(workers)
	b.RunParallel(writer)

}
<commit_msg>Add benchmark for Conn.GetRoutingKey<commit_after>// +build all integration

package gocql

import (
	"sync/atomic"

	"testing"
)

func BenchmarkConnStress(b *testing.B) {
	const workers = 16

	cluster := createCluster()
	cluster.NumConns = 1
	cluster.NumStreams = workers
	session := createSessionFromCluster(cluster, b)
	defer session.Close()

	if err := createTable(session, "CREATE TABLE IF NOT EXISTS conn_stress (id int primary key)"); err != nil {
		b.Fatal(err)
	}

	var seed uint64
	writer := func(pb *testing.PB) {
		seed := atomic.AddUint64(&seed, 1)
		var i uint64 = 0
		for pb.Next() {
			if err := session.Query("insert into conn_stress (id) values (?)", i*seed).Exec(); err != nil {
				b.Error(err)
				return
			}
			i++
		}
	}

	b.SetParallelism(workers)
	b.RunParallel(writer)

}

func BenchmarkConnRoutingKey(b *testing.B) {
	const workers = 16

	cluster := createCluster()
	cluster.NumConns = 1
	cluster.NumStreams = workers
	cluster.ConnPoolType = NewTokenAwareConnPool
	session := createSessionFromCluster(cluster, b)
	defer session.Close()

	if err := createTable(session, "CREATE TABLE IF NOT EXISTS routing_key_stress (id int primary key)"); err != nil {
		b.Fatal(err)
	}

	var seed uint64
	writer := func(pb *testing.PB) {
		seed := atomic.AddUint64(&seed, 1)
		var i uint64 = 0
		query := session.Query("insert into routing_key_stress (id) values (?)")

		for pb.Next() {
			if _, err := query.Bind(i * seed).GetRoutingKey(); err != nil {
				b.Error(err)
				return
			}
			i++
		}
	}

	b.SetParallelism(workers)
	b.RunParallel(writer)
}
<|endoftext|>


<commit_before>package null

import (
	"encoding/json"
	"testing"
)

var (
	stringJSON     = []byte(`"test"`)
	nullStringJSON = []byte(`{"String":"test","Valid":true}`)
	nullJSON       = []byte(`null`)
)

func TestStringFrom(t *testing.T) {
	str := From("test")
	assert(t, str, "From() string")

	null := From("")
	assertNull(t, null, "From() empty string")
}

func TestUnmarshalString(t *testing.T) {
	var str String
	err := json.Unmarshal(stringJSON, &str)
	maybePanic(err)
	assert(t, str, "string json")

	var ns String
	err = json.Unmarshal(nullStringJSON, &ns)
	maybePanic(err)
	assert(t, ns, "null string object json")

	var null String
	err = json.Unmarshal(nullJSON, &null)
	maybePanic(err)
	assertNull(t, null, "null json")
}

func TestMarshalString(t *testing.T) {
	str := From("test")
	data, err := json.Marshal(str)
	maybePanic(err)
	assertJSONEquals(t, data, `"test"`, "non-empty json marshal")

	// invalid values should be encoded as an empty string
	null := From("")
	data, err = json.Marshal(null)
	maybePanic(err)
	assertJSONEquals(t, data, `""`, "non-empty json marshal")
}

func TestPointer(t *testing.T) {
	str := From("test")
	ptr := str.Pointer()
	if *ptr != "test" {
		t.Errorf("bad %s string: %#v ≠ %s\n", "pointer", ptr, "test")
	}

	null := From("")
	ptr = null.Pointer()
	if ptr != nil {
		t.Errorf("bad %s: %#v ≠ %s\n", "nil pointer", ptr, "nil")
	}
}

func TestScan(t *testing.T) {
	var str String
	err := str.Scan("test")
	maybePanic(err)
	assert(t, str, "scanned string")

	var null String
	err = null.Scan(nil)
	maybePanic(err)
	assertNull(t, null, "scanned null")
}

func maybePanic(err error) {
	if err != nil {
		panic(err)
	}
}

func assert(t *testing.T, s String, from string) {
	if s.String != "test" {
		t.Errorf("bad %s string: %s ≠ %s\n", from, s.String, "test")
	}
	if !s.Valid {
		t.Error(from, "is invalid, but should be valid")
	}
}

func assertNull(t *testing.T, s String, from string) {
	if s.Valid {
		t.Error(from, "is valid, but should be invalid")
	}
}

func assertJSONEquals(t *testing.T, data []byte, cmp string, from string) {
	if string(data) != cmp {
		t.Errorf("bad %s data: %s ≠ %s\n", from, data, cmp)
	}
}
<commit_msg>update tests<commit_after>package null

import (
	"encoding/json"
	"testing"
)

var (
	stringJSON     = []byte(`"test"`)
	nullStringJSON = []byte(`{"String":"test","Valid":true}`)
	nullJSON       = []byte(`null`)
)

func TestStringFrom(t *testing.T) {
	str := StringFrom("test")
	assert(t, str, "StringFrom() string")

	null := StringFrom("")
	assertNull(t, null, "StringFrom() empty string")
}

func TestUnmarshalString(t *testing.T) {
	var str String
	err := json.Unmarshal(stringJSON, &str)
	maybePanic(err)
	assert(t, str, "string json")

	var ns String
	err = json.Unmarshal(nullStringJSON, &ns)
	maybePanic(err)
	assert(t, ns, "null string object json")

	var null String
	err = json.Unmarshal(nullJSON, &null)
	maybePanic(err)
	assertNull(t, null, "null json")
}

func TestMarshalString(t *testing.T) {
	str := StringFrom("test")
	data, err := json.Marshal(str)
	maybePanic(err)
	assertJSONEquals(t, data, `"test"`, "non-empty json marshal")

	// invalid values should be encoded as an empty string
	null := StringFrom("")
	data, err = json.Marshal(null)
	maybePanic(err)
	assertJSONEquals(t, data, `""`, "non-empty json marshal")
}

func TestPointer(t *testing.T) {
	str := StringFrom("test")
	ptr := str.Pointer()
	if *ptr != "test" {
		t.Errorf("bad %s string: %#v ≠ %s\n", "pointer", ptr, "test")
	}

	null := StringFrom("")
	ptr = null.Pointer()
	if ptr != nil {
		t.Errorf("bad %s: %#v ≠ %s\n", "nil pointer", ptr, "nil")
	}
}

func TestScan(t *testing.T) {
	var str String
	err := str.Scan("test")
	maybePanic(err)
	assert(t, str, "scanned string")

	var null String
	err = null.Scan(nil)
	maybePanic(err)
	assertNull(t, null, "scanned null")
}

func maybePanic(err error) {
	if err != nil {
		panic(err)
	}
}

func assert(t *testing.T, s String, from string) {
	if s.String != "test" {
		t.Errorf("bad %s string: %s ≠ %s\n", from, s.String, "test")
	}
	if !s.Valid {
		t.Error(from, "is invalid, but should be valid")
	}
}

func assertNull(t *testing.T, s String, from string) {
	if s.Valid {
		t.Error(from, "is valid, but should be invalid")
	}
}

func assertJSONEquals(t *testing.T, data []byte, cmp string, from string) {
	if string(data) != cmp {
		t.Errorf("bad %s data: %s ≠ %s\n", from, data, cmp)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes 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 main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func getJSON(url string, v interface{}) error {
	resp, err := http.Get(url)
	if err != nil {
		return fmt.Errorf("failed to fetch %q: %v", url, err)
	}
	decoder := json.NewDecoder(resp.Body)
	err = decoder.Decode(v)
	if err != nil {
		return fmt.Errorf("failed to decode json from %q: %v", url, err)
	}
	return nil
}

func getCurrentOncaller() (string, error) {
	oncaller := struct {
		OnCall struct {
			TestInfra string `json:"testinfra"`
		} `json:"Oncall"`
	}{}

	err := getJSON("https://storage.googleapis.com/kubernetes-jenkins/oncall.json", &oncaller)
	if err != nil {
		return "", err
	}

	return oncaller.OnCall.TestInfra, nil
}

func mapGitHubToSlack(github string) (string, error) {
	// Maps (lowercase!) GitHub usernames to Slack user IDs.
	// Add yourself when you join the oncall rotation.
	// You can mostly easily find your user ID by visiting your Slack profile, clicking "...",
	// and clicking "Copy user ID".
	mapping := map[string]string{
		"amwat":          "U9B1P2UGP",
		"chases2":        "UJ9R0FWD6",
		"cjwagner":       "U4QFZFMCM",
		"bentheelder":    "U1P7T516X",
		"fejta":          "U0E2KHQ13",
		"katharine":      "UBTBNJ6GL",
		"krzyzacy":       "U22Q65CTG",
		"mirandachrist":  "UJR3XHHNF",
		"michelle192837": "U3TRY5WV7",
		"tony-yang":      "UK3MVSP3J",
	}
	id, ok := mapping[strings.ToLower(github)]
	if !ok {
		return "", fmt.Errorf("couldn't find a Slack ID for GitHub user %q", github)
	}
	return id, nil
}

func updateGroupMembership(token, groupID, userID string) error {
	result := struct {
		Ok    bool   `json:"ok"`
		Error string `json:"error,omitempty"`
	}{}

	err := getJSON("https://slack.com/api/usergroups.users.update?token="+token+"&users="+userID+"&usergroup="+groupID, &result)
	if err != nil {
		return fmt.Errorf("couldn't make membership request: %v", err)
	}

	if !result.Ok {
		return fmt.Errorf("couldn't update membership: %s", result.Error)
	}

	return nil
}

func getTokenFromPath(path string) (string, error) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("couldn't open file: %v", err)
	}
	return strings.TrimSpace(string(content)), nil
}

type options struct {
	tokenPath string
	groupID   string
}

func parseFlags() options {
	o := options{}
	flag.StringVar(&o.tokenPath, "token-path", "/etc/slack-token", "Path to a file containing the slack token")
	flag.StringVar(&o.groupID, "group-id", "", "Slack group ID")
	flag.Parse()
	return o
}

func main() {
	o := parseFlags()

	token, err := getTokenFromPath(o.tokenPath)
	if err != nil {
		log.Fatalf("Failed to get Slack token: %v", err)
	}

	oncall, err := getCurrentOncaller()
	if err != nil {
		log.Fatalf("Failed to find current oncaller: %v", err)
	}
	log.Printf("Current oncaller: %s\n", oncall)

	userID, err := mapGitHubToSlack(oncall)
	if err != nil {
		log.Fatalf("Failed to get Slack ID: %v", err)
	}
	log.Printf("%s's slack ID: %s\n", oncall, userID)

	log.Printf("Adding slack user %s to slack usergroup %s", userID, o.groupID)
	if err := updateGroupMembership(token, o.groupID, userID); err != nil {
		log.Fatalf("Failed to update usergroup membership: %v", err)
	}
	log.Printf("Done!")
}
<commit_msg>Add clarketm to K8s-ti oncall rotation<commit_after>/*
Copyright 2019 The Kubernetes 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 main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

func getJSON(url string, v interface{}) error {
	resp, err := http.Get(url)
	if err != nil {
		return fmt.Errorf("failed to fetch %q: %v", url, err)
	}
	decoder := json.NewDecoder(resp.Body)
	err = decoder.Decode(v)
	if err != nil {
		return fmt.Errorf("failed to decode json from %q: %v", url, err)
	}
	return nil
}

func getCurrentOncaller() (string, error) {
	oncaller := struct {
		OnCall struct {
			TestInfra string `json:"testinfra"`
		} `json:"Oncall"`
	}{}

	err := getJSON("https://storage.googleapis.com/kubernetes-jenkins/oncall.json", &oncaller)
	if err != nil {
		return "", err
	}

	return oncaller.OnCall.TestInfra, nil
}

func mapGitHubToSlack(github string) (string, error) {
	// Maps (lowercase!) GitHub usernames to Slack user IDs.
	// Add yourself when you join the oncall rotation.
	// You can mostly easily find your user ID by visiting your Slack profile, clicking "...",
	// and clicking "Copy user ID".
	mapping := map[string]string{
		"amwat":          "U9B1P2UGP",
		"chases2":        "UJ9R0FWD6",
		"cjwagner":       "U4QFZFMCM",
		"clarketm":       "UKMR3JF29",
		"bentheelder":    "U1P7T516X",
		"fejta":          "U0E2KHQ13",
		"katharine":      "UBTBNJ6GL",
		"krzyzacy":       "U22Q65CTG",
		"mirandachrist":  "UJR3XHHNF",
		"michelle192837": "U3TRY5WV7",
		"tony-yang":      "UK3MVSP3J",
	}
	id, ok := mapping[strings.ToLower(github)]
	if !ok {
		return "", fmt.Errorf("couldn't find a Slack ID for GitHub user %q", github)
	}
	return id, nil
}

func updateGroupMembership(token, groupID, userID string) error {
	result := struct {
		Ok    bool   `json:"ok"`
		Error string `json:"error,omitempty"`
	}{}

	err := getJSON("https://slack.com/api/usergroups.users.update?token="+token+"&users="+userID+"&usergroup="+groupID, &result)
	if err != nil {
		return fmt.Errorf("couldn't make membership request: %v", err)
	}

	if !result.Ok {
		return fmt.Errorf("couldn't update membership: %s", result.Error)
	}

	return nil
}

func getTokenFromPath(path string) (string, error) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return "", fmt.Errorf("couldn't open file: %v", err)
	}
	return strings.TrimSpace(string(content)), nil
}

type options struct {
	tokenPath string
	groupID   string
}

func parseFlags() options {
	o := options{}
	flag.StringVar(&o.tokenPath, "token-path", "/etc/slack-token", "Path to a file containing the slack token")
	flag.StringVar(&o.groupID, "group-id", "", "Slack group ID")
	flag.Parse()
	return o
}

func main() {
	o := parseFlags()

	token, err := getTokenFromPath(o.tokenPath)
	if err != nil {
		log.Fatalf("Failed to get Slack token: %v", err)
	}

	oncall, err := getCurrentOncaller()
	if err != nil {
		log.Fatalf("Failed to find current oncaller: %v", err)
	}
	log.Printf("Current oncaller: %s\n", oncall)

	userID, err := mapGitHubToSlack(oncall)
	if err != nil {
		log.Fatalf("Failed to get Slack ID: %v", err)
	}
	log.Printf("%s's slack ID: %s\n", oncall, userID)

	log.Printf("Adding slack user %s to slack usergroup %s", userID, o.groupID)
	if err := updateGroupMembership(token, o.groupID, userID); err != nil {
		log.Fatalf("Failed to update usergroup membership: %v", err)
	}
	log.Printf("Done!")
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"

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

// SimpleChaincode basic struct
type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("failed in function main(), error is %v", err)
	}
}

var projectName string
var projectRate int
var projectPeriod, projectGoal, projectTimes int
var projectBenfiary string
var projectState string
var currentPrice float64
var currentSummary int
var userList []string

//Init function
//Step1: 获得调用init()的caller, 并且保存在"admin"中
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//get caller's certificate, and saved to "admin" state
	fmt.Println("started get caller's metatdat")
	adminCert, err := stub.GetCallerCertificate()
	if err != nil {
		return nil, errors.New("failed getting metadata")
	}
	if len(adminCert) == 0 {
		return nil, errors.New("Invalid admin certificate. Empty.")
	}
	fmt.Printf("the administrator is [%v]", adminCert)
	stub.PutState("admin", adminCert)

	//started to initialize project
	fmt.Println("started to initialize project")
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}
	projectName = args[0]                    //项目名称
	projectRate, _ = strconv.Atoi(args[1])   //项目年化利率
	projectPeriod, _ = strconv.Atoi(args[2]) //项目天数
	projectGoal, _ = strconv.Atoi(args[3])   //项目目标募集金额
	projectTimes = 1                         //项目期数
	projectBenfiary = args[4]                //项目受益人
	projectState = "draft"                   //项目当前状态
	currentPrice = 1.0

	//started to initialize the table: Shares
	fmt.Println("started to create table: Shares")
	tableErr := stub.CreateTable("Shares", []*shim.ColumnDefinition{
		&shim.ColumnDefinition{Name: "User", Type: shim.ColumnDefinition_STRING, Key: true},
		&shim.ColumnDefinition{Name: "Amount", Type: shim.ColumnDefinition_INT64, Key: false},
	})
	if tableErr != nil {
		return nil, errors.New("Failed creating AssetsOnwership table.")
	}

	return nil, nil
}

// Invoke function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")

	switch function {
	case "goPublic":
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in goPublic()")
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in pay()")
		user := args[0]
		amount := args[1]

		fmt.Println("step1: chechk whether table contains user")
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		if len(row.Columns) == 0 {
			fmt.Println("columns 0")
			fmt.Println("started to add a row")

			value, err := strconv.Atoi(amount)
			if err != nil {
				return nil, errors.New("errors in the amount")
			}
			userList = append(userList, user)
			currentSummary += value

			row := shim.Row{
				Columns: []*shim.Column{
					&shim.Column{Value: &shim.Column_String_{String_: user}},
					&shim.Column{Value: &shim.Column_Int64{Int64: int64(value)}}}}

			ok, err := stub.InsertRow("Shares", row)
			if !ok && err == nil {
				return nil, errors.New("shares was already assigned")
			}
		} else {
			fmt.Println("columns not 0")
			fmt.Println("todo we need to update")
		}

		return nil, nil //end of pay
	}

	return nil, nil
}

//Query funciton
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")

	switch function {
	case "getState":
		fmt.Println("started in function getState()")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}

		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err //end of getState
	case "getProjectState":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started in function getProjectState")
		result := projectName + "/"
		result += strconv.Itoa(projectRate) + "/"
		result += strconv.Itoa(projectPeriod) + "/"
		result += strconv.Itoa(projectGoal) + "/"
		result += strconv.Itoa(projectTimes) + "/"
		result += projectBenfiary + "/"
		result += strconv.Itoa(currentSummary) + "/"
		result += projectState

		return []byte(result), nil //end of function getProjectState

	case "getRow":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started logging in function getRow()")

		user := args[0]
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		val0 := row.Columns[0].GetString_()
		val1 := int(row.Columns[1].GetInt64())
		result := "****" + val0 + "****" + strconv.Itoa(val1)
		return []byte(result), err //end of function getRow()
	case "getUserList":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started logging in function getUserList")

		var result string
		for userStr := range userList {
			result += userStr + "***"
		}

		return []byte(result), nil //end of getUserList

	}
	return nil, nil
}
<commit_msg>demo6.go<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"

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

// SimpleChaincode basic struct
type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("failed in function main(), error is %v", err)
	}
}

var projectName string
var projectRate int
var projectPeriod, projectGoal, projectTimes int
var projectBenfiary string
var projectState string
var currentPrice float64
var currentSummary int
var userList []string

//Init function
//Step1: 获得调用init()的caller, 并且保存在"admin"中
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//get caller's certificate, and saved to "admin" state
	fmt.Println("started get caller's metatdat")
	adminCert, err := stub.GetCallerCertificate()
	if err != nil {
		return nil, errors.New("failed getting metadata")
	}
	if len(adminCert) == 0 {
		return nil, errors.New("Invalid admin certificate. Empty.")
	}
	fmt.Printf("the administrator is [%v]", adminCert)
	stub.PutState("admin", adminCert)

	//started to initialize project
	fmt.Println("started to initialize project")
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}
	projectName = args[0]                    //项目名称
	projectRate, _ = strconv.Atoi(args[1])   //项目年化利率
	projectPeriod, _ = strconv.Atoi(args[2]) //项目天数
	projectGoal, _ = strconv.Atoi(args[3])   //项目目标募集金额
	projectTimes = 1                         //项目期数
	projectBenfiary = args[4]                //项目受益人
	projectState = "draft"                   //项目当前状态
	currentPrice = 1.0

	//started to initialize the table: Shares
	fmt.Println("started to create table: Shares")
	tableErr := stub.CreateTable("Shares", []*shim.ColumnDefinition{
		&shim.ColumnDefinition{Name: "User", Type: shim.ColumnDefinition_STRING, Key: true},
		&shim.ColumnDefinition{Name: "Amount", Type: shim.ColumnDefinition_INT64, Key: false},
	})
	if tableErr != nil {
		return nil, errors.New("Failed creating AssetsOnwership table.")
	}

	return nil, nil
}

// Invoke function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")

	switch function {
	case "goPublic":
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in goPublic()")
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in pay()")
		user := args[0]
		amount := args[1]

		fmt.Println("step1: chechk whether table contains user")
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		if len(row.Columns) == 0 {
			fmt.Println("columns 0")
			fmt.Println("started to add a row")

			value, err := strconv.Atoi(amount)
			if err != nil {
				return nil, errors.New("errors in the amount")
			}
			userList = append(userList, user)
			currentSummary += value

			row := shim.Row{
				Columns: []*shim.Column{
					&shim.Column{Value: &shim.Column_String_{String_: user}},
					&shim.Column{Value: &shim.Column_Int64{Int64: int64(value)}}}}

			ok, err := stub.InsertRow("Shares", row)
			if !ok && err == nil {
				return nil, errors.New("shares was already assigned")
			}
		} else {
			fmt.Println("columns not 0")
			fmt.Println("todo we need to update")
		}

		return nil, nil //end of pay
	}

	return nil, nil
}

//Query funciton
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")

	switch function {
	case "getState":
		fmt.Println("started in function getState()")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}

		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err //end of getState
	case "getProjectState":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started in function getProjectState")
		result := projectName + "/"
		result += strconv.Itoa(projectRate) + "/"
		result += strconv.Itoa(projectPeriod) + "/"
		result += strconv.Itoa(projectGoal) + "/"
		result += strconv.Itoa(projectTimes) + "/"
		result += projectBenfiary + "/"
		result += strconv.Itoa(currentSummary) + "/"
		result += projectState

		return []byte(result), nil //end of function getProjectState

	case "getRow":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started logging in function getRow()")

		user := args[0]
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		val0 := row.Columns[0].GetString_()
		val1 := int(row.Columns[1].GetInt64())
		result := "****" + val0 + "****" + strconv.Itoa(val1)
		return []byte(result), err //end of function getRow()
	case "getUserList":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started logging in function getUserList")

		var result string
		for _, userStr := range userList {
			result += userStr + "***"
		}

		return []byte(result), nil //end of getUserList
	}
	return nil, nil
}
<|endoftext|>


<commit_before>package edit

import (
	"fmt"
	"strings"
	"unicode/utf8"
)

// Completion subsystem.

// Interface.

type completion struct {
	completer  string
	begin, end int
	all        []*candidate

	filtering  bool
	filter     string
	candidates []*candidate
	selected   int
	firstShown int
	lastShown  int
	height     int
}

func (*completion) Mode() ModeType {
	return modeCompletion
}

func (c *completion) ModeLine(width int) *buffer {
	b := newBuffer(width)
	b.writes(" ", "")
	// Write title
	title := fmt.Sprintf("COMPLETING %s", c.completer)
	b.writes(TrimWcWidth(title, width), styleForMode)
	// Write filter
	if c.filtering {
		b.writes(" ", "")
		b.writes(c.filter, styleForFilter)
		b.dot = b.cursor()
	}
	// Write horizontal scrollbar, using the remaining space
	if c.firstShown > 0 || c.lastShown < len(c.candidates)-1 {
		scrollbarWidth := width - 1 - lineWidth(b.cells[len(b.cells)-1])
		if scrollbarWidth >= 3 {
			b.writes(" ", "")
			writeHorizontalScrollbar(b, len(c.candidates), c.firstShown, c.lastShown, scrollbarWidth)
		}
	}

	return b
}

func startCompl(ed *Editor) {
	startCompletionInner(ed, false)
}

func complPrefixOrStartCompl(ed *Editor) {
	startCompletionInner(ed, true)
}

func complUp(ed *Editor) {
	ed.completion.prev(false)
}

func complDown(ed *Editor) {
	ed.completion.next(false)
}

func complLeft(ed *Editor) {
	if c := ed.completion.selected - ed.completion.height; c >= 0 {
		ed.completion.selected = c
	}
}

func complRight(ed *Editor) {
	if c := ed.completion.selected + ed.completion.height; c < len(ed.completion.candidates) {
		ed.completion.selected = c
	}
}

func complDownCycle(ed *Editor) {
	ed.completion.next(true)
}

// acceptCompletion accepts currently selected completion candidate.
func complAccept(ed *Editor) {
	c := ed.completion
	if 0 <= c.selected && c.selected < len(c.candidates) {
		ed.line, ed.dot = c.apply(ed.line, ed.dot)
	}
	ed.mode = &ed.insert
}

func complDefault(ed *Editor) {
	k := ed.lastKey
	c := &ed.completion
	if c.filtering && likeChar(k) {
		c.changeFilter(c.filter + string(k.Rune))
	} else if c.filtering && k == (Key{Backspace, 0}) {
		_, size := utf8.DecodeLastRuneInString(c.filter)
		if size > 0 {
			c.changeFilter(c.filter[:len(c.filter)-size])
		}
	} else {
		complAccept(ed)
		ed.nextAction = action{typ: reprocessKey}
	}
}

func complTriggerFilter(ed *Editor) {
	c := &ed.completion
	if c.filtering {
		c.filtering = false
		c.changeFilter("")
	} else {
		c.filtering = true
	}
}

type candidate struct {
	text    string
	display styled
	suffix  string
}

func (comp *completion) selectedCandidate() *candidate {
	if comp.selected == -1 {
		return &candidate{}
	}
	return comp.candidates[comp.selected]
}

// apply returns the line and dot after applying a candidate.
func (comp *completion) apply(line string, dot int) (string, int) {
	text := comp.selectedCandidate().text
	return line[:comp.begin] + text + line[comp.end:], comp.begin + len(text)
}

func (c *completion) prev(cycle bool) {
	c.selected--
	if c.selected == -1 {
		if cycle {
			c.selected = len(c.candidates) - 1
		} else {
			c.selected++
		}
	}
}

func (c *completion) next(cycle bool) {
	c.selected++
	if c.selected == len(c.candidates) {
		if cycle {
			c.selected = 0
		} else {
			c.selected--
		}
	}
}

func startCompletionInner(ed *Editor, acceptPrefix bool) {
	token := tokenAtDot(ed)
	node := token.Node
	if node == nil {
		return
	}

	c := &completion{begin: -1}
	for _, compl := range completers {
		begin, end, candidates := compl.completer(node, ed)
		if begin >= 0 {
			c.completer = compl.name
			c.begin, c.end, c.all = begin, end, candidates
			c.candidates = c.all
			break
		}
	}

	if c.begin < 0 {
		ed.addTip("unsupported completion :(")
	} else if len(c.candidates) == 0 {
		ed.addTip("no candidate for %s", c.completer)
	} else {
		if acceptPrefix {
			// If there is a non-empty longest common prefix, insert it and
			// don't start completion mode.
			//
			// As a special case, when there is exactly one candidate, it is
			// immeidately accepted.
			prefix := c.candidates[0].text
			for _, cand := range c.candidates[1:] {
				prefix = commonPrefix(prefix, cand.text)
				if prefix == "" {
					break
				}
			}
			if prefix != "" && prefix != ed.line[c.begin:c.end] {
				ed.line = ed.line[:c.begin] + prefix + ed.line[c.end:]
				ed.dot = c.begin + len(prefix)
				return
			}
		}
		// Fix .display.text
		for _, cand := range c.candidates {
			if cand.display.text == "" {
				cand.display.text = cand.text
			}
		}
		ed.completion = *c
		ed.mode = &ed.completion
	}
}

func tokenAtDot(ed *Editor) Token {
	if len(ed.tokens) == 0 || ed.dot > len(ed.line) {
		return Token{}
	}
	if ed.dot == len(ed.line) {
		return ed.tokens[len(ed.tokens)-1]
	}
	for _, token := range ed.tokens {
		if ed.dot < token.Node.End() {
			return token
		}
	}
	return Token{}
}

// commonPrefix returns the longest common prefix of two strings.
func commonPrefix(s, t string) string {
	for i, r := range s {
		if i >= len(t) {
			return s[:i]
		}
		r2, _ := utf8.DecodeRuneInString(t[i:])
		if r2 != r {
			return s[:i]
		}
	}
	return s
}

const completionListingColMargin = 2

// maxWidth finds the maximum wcwidth of display texts of candidates [lo, hi).
// hi may be larger than the number of candidates, in which case it is truncated
// to the number of candidates.
func (comp *completion) maxWidth(lo, hi int) int {
	if hi > len(comp.candidates) {
		hi = len(comp.candidates)
	}
	width := 0
	for i := lo; i < hi; i++ {
		w := WcWidths(comp.candidates[i].display.text)
		if width < w {
			width = w
		}
	}
	return width
}

func (comp *completion) List(width, maxHeight int) *buffer {
	b := newBuffer(width)
	cands := comp.candidates
	if len(cands) == 0 {
		b.writes(TrimWcWidth("(no result)", width), "")
		return b
	}
	if maxHeight <= 1 || width <= 2 {
		b.writes(TrimWcWidth("(terminal too small)", width), "")
		return b
	}
	height := maxHeight - 1

	comp.height = min(height, len(cands))

	// Determine the first column to show. We start with the column in which the
	// selected one is found, moving to the left until either the width is
	// exhausted, or the old value of firstShown has been hit.
	first := comp.selected / height * height
	w := comp.maxWidth(first, first+height)
	for ; first > comp.firstShown; first -= height {
		dw := comp.maxWidth(first-height, first) + completionListingColMargin
		if w+dw > width-2 {
			break
		}
		w += dw
	}
	comp.firstShown = first

	var i, j int
	remainedWidth := width - 2
	margin := 0
	// Show the results in columns, until width is exceeded.
	for i = first; i < len(cands); i += height {
		if i > first {
			margin = completionListingColMargin
		}
		// Determine the width of the column (without the margin)
		colWidth := comp.maxWidth(i, min(i+height, len(cands)))
		if colWidth > remainedWidth-margin {
			colWidth = remainedWidth - margin
		}

		col := newBuffer(margin + colWidth)
		for j = i; j < i+height && j < len(cands); j++ {
			if j > i {
				col.newline()
			}
			col.writePadding(margin, "")
			style := cands[j].display.style
			if j == comp.selected {
				style += styleForSelected
			}
			col.writes(ForceWcWidth(cands[j].display.text, colWidth), style)
		}

		b.extendHorizontal(col, 1)
		remainedWidth -= colWidth + margin
		if remainedWidth <= completionListingColMargin {
			break
		}
	}
	comp.lastShown = j - 1
	return b
}

func (c *completion) changeFilter(f string) {
	c.filter = f
	if f == "" {
		c.candidates = c.all
		return
	}
	c.candidates = nil
	for _, cand := range c.all {
		if strings.Contains(cand.display.text, f) {
			c.candidates = append(c.candidates, cand)
		}
	}
	if len(c.candidates) > 0 {
		c.selected = 0
	} else {
		c.selected = -1
	}
}
<commit_msg>No need to reserve one line for scrollbar in completion mode.<commit_after>package edit

import (
	"fmt"
	"strings"
	"unicode/utf8"
)

// Completion subsystem.

// Interface.

type completion struct {
	completer  string
	begin, end int
	all        []*candidate

	filtering  bool
	filter     string
	candidates []*candidate
	selected   int
	firstShown int
	lastShown  int
	height     int
}

func (*completion) Mode() ModeType {
	return modeCompletion
}

func (c *completion) ModeLine(width int) *buffer {
	b := newBuffer(width)
	b.writes(" ", "")
	// Write title
	title := fmt.Sprintf("COMPLETING %s", c.completer)
	b.writes(TrimWcWidth(title, width), styleForMode)
	// Write filter
	if c.filtering {
		b.writes(" ", "")
		b.writes(c.filter, styleForFilter)
		b.dot = b.cursor()
	}
	// Write horizontal scrollbar, using the remaining space
	if c.firstShown > 0 || c.lastShown < len(c.candidates)-1 {
		scrollbarWidth := width - 1 - lineWidth(b.cells[len(b.cells)-1])
		if scrollbarWidth >= 3 {
			b.writes(" ", "")
			writeHorizontalScrollbar(b, len(c.candidates), c.firstShown, c.lastShown, scrollbarWidth)
		}
	}

	return b
}

func startCompl(ed *Editor) {
	startCompletionInner(ed, false)
}

func complPrefixOrStartCompl(ed *Editor) {
	startCompletionInner(ed, true)
}

func complUp(ed *Editor) {
	ed.completion.prev(false)
}

func complDown(ed *Editor) {
	ed.completion.next(false)
}

func complLeft(ed *Editor) {
	if c := ed.completion.selected - ed.completion.height; c >= 0 {
		ed.completion.selected = c
	}
}

func complRight(ed *Editor) {
	if c := ed.completion.selected + ed.completion.height; c < len(ed.completion.candidates) {
		ed.completion.selected = c
	}
}

func complDownCycle(ed *Editor) {
	ed.completion.next(true)
}

// acceptCompletion accepts currently selected completion candidate.
func complAccept(ed *Editor) {
	c := ed.completion
	if 0 <= c.selected && c.selected < len(c.candidates) {
		ed.line, ed.dot = c.apply(ed.line, ed.dot)
	}
	ed.mode = &ed.insert
}

func complDefault(ed *Editor) {
	k := ed.lastKey
	c := &ed.completion
	if c.filtering && likeChar(k) {
		c.changeFilter(c.filter + string(k.Rune))
	} else if c.filtering && k == (Key{Backspace, 0}) {
		_, size := utf8.DecodeLastRuneInString(c.filter)
		if size > 0 {
			c.changeFilter(c.filter[:len(c.filter)-size])
		}
	} else {
		complAccept(ed)
		ed.nextAction = action{typ: reprocessKey}
	}
}

func complTriggerFilter(ed *Editor) {
	c := &ed.completion
	if c.filtering {
		c.filtering = false
		c.changeFilter("")
	} else {
		c.filtering = true
	}
}

type candidate struct {
	text    string
	display styled
	suffix  string
}

func (comp *completion) selectedCandidate() *candidate {
	if comp.selected == -1 {
		return &candidate{}
	}
	return comp.candidates[comp.selected]
}

// apply returns the line and dot after applying a candidate.
func (comp *completion) apply(line string, dot int) (string, int) {
	text := comp.selectedCandidate().text
	return line[:comp.begin] + text + line[comp.end:], comp.begin + len(text)
}

func (c *completion) prev(cycle bool) {
	c.selected--
	if c.selected == -1 {
		if cycle {
			c.selected = len(c.candidates) - 1
		} else {
			c.selected++
		}
	}
}

func (c *completion) next(cycle bool) {
	c.selected++
	if c.selected == len(c.candidates) {
		if cycle {
			c.selected = 0
		} else {
			c.selected--
		}
	}
}

func startCompletionInner(ed *Editor, acceptPrefix bool) {
	token := tokenAtDot(ed)
	node := token.Node
	if node == nil {
		return
	}

	c := &completion{begin: -1}
	for _, compl := range completers {
		begin, end, candidates := compl.completer(node, ed)
		if begin >= 0 {
			c.completer = compl.name
			c.begin, c.end, c.all = begin, end, candidates
			c.candidates = c.all
			break
		}
	}

	if c.begin < 0 {
		ed.addTip("unsupported completion :(")
	} else if len(c.candidates) == 0 {
		ed.addTip("no candidate for %s", c.completer)
	} else {
		if acceptPrefix {
			// If there is a non-empty longest common prefix, insert it and
			// don't start completion mode.
			//
			// As a special case, when there is exactly one candidate, it is
			// immeidately accepted.
			prefix := c.candidates[0].text
			for _, cand := range c.candidates[1:] {
				prefix = commonPrefix(prefix, cand.text)
				if prefix == "" {
					break
				}
			}
			if prefix != "" && prefix != ed.line[c.begin:c.end] {
				ed.line = ed.line[:c.begin] + prefix + ed.line[c.end:]
				ed.dot = c.begin + len(prefix)
				return
			}
		}
		// Fix .display.text
		for _, cand := range c.candidates {
			if cand.display.text == "" {
				cand.display.text = cand.text
			}
		}
		ed.completion = *c
		ed.mode = &ed.completion
	}
}

func tokenAtDot(ed *Editor) Token {
	if len(ed.tokens) == 0 || ed.dot > len(ed.line) {
		return Token{}
	}
	if ed.dot == len(ed.line) {
		return ed.tokens[len(ed.tokens)-1]
	}
	for _, token := range ed.tokens {
		if ed.dot < token.Node.End() {
			return token
		}
	}
	return Token{}
}

// commonPrefix returns the longest common prefix of two strings.
func commonPrefix(s, t string) string {
	for i, r := range s {
		if i >= len(t) {
			return s[:i]
		}
		r2, _ := utf8.DecodeRuneInString(t[i:])
		if r2 != r {
			return s[:i]
		}
	}
	return s
}

const completionListingColMargin = 2

// maxWidth finds the maximum wcwidth of display texts of candidates [lo, hi).
// hi may be larger than the number of candidates, in which case it is truncated
// to the number of candidates.
func (comp *completion) maxWidth(lo, hi int) int {
	if hi > len(comp.candidates) {
		hi = len(comp.candidates)
	}
	width := 0
	for i := lo; i < hi; i++ {
		w := WcWidths(comp.candidates[i].display.text)
		if width < w {
			width = w
		}
	}
	return width
}

func (comp *completion) List(width, height int) *buffer {
	b := newBuffer(width)
	cands := comp.candidates
	if len(cands) == 0 {
		b.writes(TrimWcWidth("(no result)", width), "")
		return b
	}
	if height <= 1 || width <= 2 {
		b.writes(TrimWcWidth("(terminal too small)", width), "")
		return b
	}

	comp.height = min(height, len(cands))

	// Determine the first column to show. We start with the column in which the
	// selected one is found, moving to the left until either the width is
	// exhausted, or the old value of firstShown has been hit.
	first := comp.selected / height * height
	w := comp.maxWidth(first, first+height)
	for ; first > comp.firstShown; first -= height {
		dw := comp.maxWidth(first-height, first) + completionListingColMargin
		if w+dw > width-2 {
			break
		}
		w += dw
	}
	comp.firstShown = first

	var i, j int
	remainedWidth := width - 2
	margin := 0
	// Show the results in columns, until width is exceeded.
	for i = first; i < len(cands); i += height {
		if i > first {
			margin = completionListingColMargin
		}
		// Determine the width of the column (without the margin)
		colWidth := comp.maxWidth(i, min(i+height, len(cands)))
		if colWidth > remainedWidth-margin {
			colWidth = remainedWidth - margin
		}

		col := newBuffer(margin + colWidth)
		for j = i; j < i+height && j < len(cands); j++ {
			if j > i {
				col.newline()
			}
			col.writePadding(margin, "")
			style := cands[j].display.style
			if j == comp.selected {
				style += styleForSelected
			}
			col.writes(ForceWcWidth(cands[j].display.text, colWidth), style)
		}

		b.extendHorizontal(col, 1)
		remainedWidth -= colWidth + margin
		if remainedWidth <= completionListingColMargin {
			break
		}
	}
	comp.lastShown = j - 1
	return b
}

func (c *completion) changeFilter(f string) {
	c.filter = f
	if f == "" {
		c.candidates = c.all
		return
	}
	c.candidates = nil
	for _, cand := range c.all {
		if strings.Contains(cand.display.text, f) {
			c.candidates = append(c.candidates, cand)
		}
	}
	if len(c.candidates) > 0 {
		c.selected = 0
	} else {
		c.selected = -1
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"strconv"
	"time"

	"github.com/vlam321/Inf191BloomFilter/bloomDataGenerator"
	"github.com/vlam321/Inf191BloomFilter/databaseAccessObj"
	"github.com/vlam321/Inf191BloomFilter/payload"

	"github.com/cyberdelia/go-metrics-graphite"
	metrics "github.com/rcrowley/go-metrics"
)

var endpoint string
var host string

type Payload struct {
	UserId int
	Emails []string
}

// conv2Json converts payload input into JSON
func conv2Json(payload Payload) []byte {
	data, err := json.Marshal(payload)
	if err != nil {
		log.Printf("Error json marshaling: %v\n", err)
		return nil
	}
	return data
}

func makeMap(emails []string) map[string]bool {
	quickMap := make(map[string]bool)
	for i := range emails {
		quickMap[emails[i]] = true
	}
	return quickMap
}

// checkResult takes in the expected and actual values and
// calculate the hit and miss ratio and sends the data to
// graphite
func checkResult(unsubbed, subbed map[int][]string, res []string) {
	unsubbedMap := makeMap(unsubbed[0])
	subbedMap := makeMap(subbed[0])
	hit := 0
	miss := 0
	for i := range res {
		if ok := (unsubbedMap[res[i]] && !subbedMap[res[i]]); ok {
			hit += 1
		} else {
			miss += 1
		}
	}
	if len(unsubbedMap) > len(res) {
		miss += len(unsubbedMap) - len(res)
	}
	metrics.GetOrRegisterGauge("result.hit", nil).Update(int64(hit))
	metrics.GetOrRegisterGauge("result.miss", nil).Update(int64(miss))
}

// attackBloomFilter hit endpoint with test data
func attackBloomFilter(dao *databaseAccessObj.Conn, expectedTrues, expectedFalse int, endpoint string, userID int) {

	unsubbed := dao.SelectRandSubset(userID, expectedTrues)
	subbed := bloomDataGenerator.GenData(1, expectedFalse, expectedFalse+1)

	var dataSum []string
	dataSum = append(dataSum, unsubbed[userID]...)
	dataSum = append(dataSum, subbed[0]...)

	pyld := Payload{userID, dataSum}
	jsn := conv2Json(pyld)

	// membershipEndpoint := "http://" + endpoint + ":9090/filterUnsubscribed"
	// log.Println(membershipEndpoint)

	start := time.Now()
	client := &http.Client{}
	//_, err := http.Post(endpoint, "application/json; charset=utf-8", bytes.NewBuffer(jsn))
	r, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(jsn))
	if err != nil {
		log.Printf("Error in post request: %v\n", err)
		return
	}
	r.Header.Set("userid", strconv.Itoa(pyld.UserId))
	r.Header.Add("Content-Type", "application/json; charset=utf-8")
	res, err := client.Do(r)
	latency := time.Since(start).Nanoseconds() / 1000000

	if err != nil {
		log.Printf("Error in post request: %v\n", err)
		return
	}

	log.Printf("Sent request to filter with payload size of %d emails (expected reponse size = %d emails).", len(dataSum), expectedTrues)

	defer res.Body.Close()
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		log.Printf("Error reading body: %v\n", err)
		return
	}

	//var result map[int][]string
	var result payload.Payload
	err = json.Unmarshal(body, &result)
	if err != nil {
		log.Printf("Error unmarshaling body: %v\n", err)
		return
	}

	metrics.GetOrRegisterGauge(fmt.Sprintf("%s.request.latency", host), nil).Update(int64(latency))
	metrics.GetOrRegisterGauge(fmt.Sprintf("%s.request.trues", host), nil).Update(int64(len(unsubbed[userID])))
	metrics.GetOrRegisterGauge(fmt.Sprintf("%s.request.falses", host), nil).Update(int64(len(dataSum) - len(unsubbed[userID])))
	// checkResult(unsubbed, subbed, result.Emails)
}

// sendRequest attackBloomFilter every ms
func sendRequest(dao *databaseAccessObj.Conn, ms int32, endpoint string, userID int) {
	ticker := time.NewTicker(time.Duration(ms) * time.Millisecond)
	for _ = range ticker.C {
		attackBloomFilter(dao, 500, 500, endpoint, userID)
	}
}

func main() {
	dao := databaseAccessObj.New()
	defer dao.CloseConnection()

	addr, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:2003", os.Getenv("GRAPHITE_IP")))
	host, _ = os.Hostname()

	go graphite.Graphite(metrics.DefaultRegistry, 10e9, "metrics", addr)

	endpoint = os.Getenv("ENDPOINT")
	userID, err := strconv.Atoi(os.Getenv("USERID"))
	if err != nil {
		log.Printf("Client simulator: %v\n", err.Error())
	}

	log.Printf("ATTACKING ROUTER @ %s\n", endpoint)
	go sendRequest(dao, 1, endpoint, userID)

	http.ListenAndServe(":9091", nil)
}
<commit_msg>Commented out result checking in client simulation and added import for pprof<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	_ "net/http/pprof"
	"os"
	"strconv"
	"time"

	"github.com/vlam321/Inf191BloomFilter/bloomDataGenerator"
	"github.com/vlam321/Inf191BloomFilter/databaseAccessObj"

	"github.com/cyberdelia/go-metrics-graphite"
	metrics "github.com/rcrowley/go-metrics"
)

var endpoint string
var host string

type Payload struct {
	UserId int
	Emails []string
}

// conv2Json converts payload input into JSON
func conv2Json(payload Payload) []byte {
	data, err := json.Marshal(payload)
	if err != nil {
		log.Printf("Error json marshaling: %v\n", err)
		return nil
	}
	return data
}

func makeMap(emails []string) map[string]bool {
	quickMap := make(map[string]bool)
	for i := range emails {
		quickMap[emails[i]] = true
	}
	return quickMap
}

// checkResult takes in the expected and actual values and
// calculate the hit and miss ratio and sends the data to
// graphite
func checkResult(unsubbed, subbed map[int][]string, res []string) {
	unsubbedMap := makeMap(unsubbed[0])
	subbedMap := makeMap(subbed[0])
	hit := 0
	miss := 0
	for i := range res {
		if ok := (unsubbedMap[res[i]] && !subbedMap[res[i]]); ok {
			hit += 1
		} else {
			miss += 1
		}
	}
	if len(unsubbedMap) > len(res) {
		miss += len(unsubbedMap) - len(res)
	}
	metrics.GetOrRegisterGauge("result.hit", nil).Update(int64(hit))
	metrics.GetOrRegisterGauge("result.miss", nil).Update(int64(miss))
}

// attackBloomFilter hit endpoint with test data
func attackBloomFilter(dao *databaseAccessObj.Conn, expectedTrues, expectedFalse int, endpoint string, userID int) {

	unsubbed := dao.SelectRandSubset(userID, expectedTrues)
	subbed := bloomDataGenerator.GenData(1, expectedFalse, expectedFalse+1)

	var dataSum []string
	dataSum = append(dataSum, unsubbed[userID]...)
	dataSum = append(dataSum, subbed[0]...)

	pyld := Payload{userID, dataSum}
	jsn := conv2Json(pyld)

	// membershipEndpoint := "http://" + endpoint + ":9090/filterUnsubscribed"
	// log.Println(membershipEndpoint)

	client := &http.Client{}
	//_, err := http.Post(endpoint, "application/json; charset=utf-8", bytes.NewBuffer(jsn))
	r, err := http.NewRequest("POST", endpoint, bytes.NewBuffer(jsn))
	if err != nil {
		log.Printf("Error in post request: %v\n", err)
		return
	}
	r.Header.Set("userid", strconv.Itoa(pyld.UserId))
	r.Header.Add("Content-Type", "application/json; charset=utf-8")
	start := time.Now()
	_, err = client.Do(r)
	latency := time.Since(start).Nanoseconds() / 1000000

	if err != nil {
		log.Printf("Error in post request: %v\n", err)
		return
	}

	log.Printf("Sent request to filter with payload size of %d emails (expected reponse size = %d emails).", len(dataSum), expectedTrues)

	/*
		defer res.Body.Close()
		body, err := ioutil.ReadAll(res.Body)
		if err != nil {
			log.Printf("Error reading body: %v\n", err)
			return
		}

		//var result map[int][]string
		var result payload.Payload
		err = json.Unmarshal(body, &result)
		if err != nil {
			log.Printf("Error unmarshaling body: %v\n", err)
			return
		}
	*/
	metrics.GetOrRegisterGauge(fmt.Sprintf("%s.request.latency", host), nil).Update(int64(latency))
	metrics.GetOrRegisterGauge(fmt.Sprintf("%s.request.trues", host), nil).Update(int64(len(unsubbed[userID])))
	metrics.GetOrRegisterGauge(fmt.Sprintf("%s.request.falses", host), nil).Update(int64(len(dataSum) - len(unsubbed[userID])))
	// checkResult(unsubbed, subbed, result.Emails)
}

// sendRequest attackBloomFilter every ms
func sendRequest(dao *databaseAccessObj.Conn, ms int32, endpoint string, userID int) {
	ticker := time.NewTicker(time.Duration(ms) * time.Millisecond)
	for _ = range ticker.C {
		attackBloomFilter(dao, 500, 500, endpoint, userID)
	}
}

func main() {
	dao := databaseAccessObj.New()
	defer dao.CloseConnection()

	addr, _ := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:2003", os.Getenv("GRAPHITE_IP")))
	host, _ = os.Hostname()

	go graphite.Graphite(metrics.DefaultRegistry, 10e9, "metrics", addr)

	endpoint = os.Getenv("ENDPOINT")
	userID, err := strconv.Atoi(os.Getenv("USERID"))
	if err != nil {
		log.Printf("Client simulator: %v\n", err.Error())
	}

	log.Printf("ATTACKING ROUTER @ %s\n", endpoint)
	go sendRequest(dao, 1, endpoint, userID)

	http.ListenAndServe(":9091", nil)
}
<|endoftext|>


<commit_before><commit_msg>cmd/protoc-gen-go: always register file descriptor<commit_after><|endoftext|>


<commit_before>package emil_test

import (
	"github.com/ujanssen/emil"
	"testing"
)

var db *emil.EndGameDb

func init() {
	db = emil.NewEndGameDb()
}

/*
  a b c d e f g h
8         k       8
7                 7
6         K       6
5                 5
4                 4
3                 3
2                 2
1               R 1
  a b c d e f g h
*/
func TestFindMoveRh1h8(t *testing.T) {
	board := emil.NewBoard()
	board.Setup(emil.WhiteKing, emil.E6)
	board.Setup(emil.BlackKing, emil.E8)
	board.Setup(emil.WhiteRock, emil.H1)

	want := "Rh1h8"
	move := db.Find(board)
	if move == nil {
		t.Errorf("the move should be %s, got nil", want)
	} else {
		got := move.String()
		if got != want {
			t.Errorf("the move should be %s, got %s", want, got)
		}
	}
}

/*
  a b c d e f g h
8               k 8
7           K     7
6         R       6
5                 5
4                 4
3                 3
2                 2
1                 1
  a b c d e f g h
*/
func TestFindMoveRe6h6(t *testing.T) {
	board := emil.NewBoard()
	board.Setup(emil.WhiteKing, emil.F7)
	board.Setup(emil.BlackKing, emil.H8)
	board.Setup(emil.WhiteRock, emil.E6)

	want := "Re6h6"
	move := db.Find(board)
	if move == nil {
		t.Errorf("the move should be %s, got nil", want)
	} else {
		got := move.String()
		if got != want {
			t.Errorf("the move should be %s, got %s", want, got)
		}
	}
}
<commit_msg>add test<commit_after>package emil_test

import (
	"github.com/ujanssen/emil"
	"testing"
)

var db *emil.EndGameDb

func init() {
	db = emil.NewEndGameDb()
}

/*
  a b c d e f g h
8         k       8
7                 7
6         K       6
5                 5
4                 4
3                 3
2                 2
1               R 1
  a b c d e f g h
*/
func TestFindMoveRh1h8(t *testing.T) {
	board := emil.NewBoard()
	board.Setup(emil.WhiteKing, emil.E6)
	board.Setup(emil.BlackKing, emil.E8)
	board.Setup(emil.WhiteRock, emil.H1)

	want := "Rh1h8"
	move := db.Find(board)
	if move == nil {
		t.Errorf("the move should be %s, got nil", want)
	} else {
		got := move.String()
		if got != want {
			t.Errorf("the move should be %s, got %s", want, got)
		}
	}
}

/*
  a b c d e f g h
8               k 8
7           K     7
6         R       6
5                 5
4                 4
3                 3
2                 2
1                 1
  a b c d e f g h
*/
func TestFindMoveRe6h6(t *testing.T) {
	board := emil.NewBoard()
	board.Setup(emil.WhiteKing, emil.F7)
	board.Setup(emil.BlackKing, emil.H8)
	board.Setup(emil.WhiteRock, emil.E6)

	want := "Re6h6"
	move := db.Find(board)
	if move == nil {
		t.Errorf("the move should be %s, got nil", want)
	} else {
		got := move.String()
		if got != want {
			t.Errorf("the move should be %s, got %s", want, got)
		}
	}
}

/*
  a b c d e f g h
8 R R R   k   R R 8
7                 7
6         K       6
5                 5
4                 4
3                 3
2                 2
1                 1
  a b c d e f g h
*/
func TestFindFiveMatesWithBlackKingOnE8(t *testing.T) {
	boards := db.FindMate(emil.BlackKing, emil.E8)
	if len(boards) != 5 {
		t.Errorf("len(boards) should be 5, got %d", len(boards))
	}
}
<|endoftext|>


<commit_before>package kvdb

import (
	"fmt"
	"sync"
)

var (
	instance   Kvdb
	datastores = make(map[string]DatastoreInit)
	lock       sync.Mutex
)

// Instance returns instance set via SetInstance, nil if none was set.
func Instance() Kvdb {
	return instance
}

// SetInstance sets the singleton instance.
func SetInstance(kvdb Kvdb) error {
	if instance == nil {
		lock.Lock()
		defer lock.Unlock()
		if instance == nil {
			instance = kvdb
			return nil
		}
	}
	return fmt.Errorf("Kvdb instance is already set to %q", instance.String())
}

// New return a new instance of KVDB as specified by datastore name.
// If domain is set all requests to KVDB are prefixed by domain.
// options is interpreted by backend KVDB.
func New(
	name string,
	domain string,
	machines []string,
) (Kvdb, error) {
	if dsInit, exists := datastores[name]; exists {
		kvdb, err := dsInit(domain, machines)
		return kvdb, err
	}
	return nil, ErrNotSupported
}

// Register adds specified datastore backend to the list of options.
func Register(name string, dsInit DatastoreInit) error {
	if _, exists := datastores[name]; exists {
		return fmt.Errorf("Datastore provider %q is already registered", name)
	}
	datastores[name] = dsInit
	return nil
}
<commit_msg>properly lock<commit_after>package kvdb

import (
	"fmt"
	"sync"
)

var (
	instance   Kvdb
	datastores = make(map[string]DatastoreInit)
	lock       sync.RWMutex
)

// Instance returns instance set via SetInstance, nil if none was set.
func Instance() Kvdb {
	return instance
}

// SetInstance sets the singleton instance.
func SetInstance(kvdb Kvdb) error {
	if instance == nil {
		lock.Lock()
		defer lock.Unlock()
		if instance == nil {
			instance = kvdb
			return nil
		}
	}
	return fmt.Errorf("Kvdb instance is already set to %q", instance.String())
}

// New return a new instance of KVDB as specified by datastore name.
// If domain is set all requests to KVDB are prefixed by domain.
// options is interpreted by backend KVDB.
func New(
	name string,
	domain string,
	machines []string,
) (Kvdb, error) {
	lock.RLock()
	defer lock.RUnlock()
	if dsInit, exists := datastores[name]; exists {
		kvdb, err := dsInit(domain, machines)
		return kvdb, err
	}
	return nil, ErrNotSupported
}

// Register adds specified datastore backend to the list of options.
func Register(name string, dsInit DatastoreInit) error {
	lock.Lock()
	defer lock.Unlock()
	if _, exists := datastores[name]; exists {
		return fmt.Errorf("Datastore provider %q is already registered", name)
	}
	datastores[name] = dsInit
	return nil
}
<|endoftext|>


<commit_before>package main

import(
	"fmt"
	"strings"
)

type LaTeXOut struct{

}

func (lo LaTeXOut) output(s []string, rpmInfo map[string] *RpmInfo) {
	fmt.Println("\\documentclass[11pt,landscape]{article}")
	fmt.Println("\\usepackage[landscape,paperwidth=11in,paperheight=8.5in]{geometry}")
	fmt.Println("\\usepackage{longtable}")
	fmt.Println("\\usepackage[hyphens]{url}")

	fmt.Println("\\oddsidemargin -.5cm")
	fmt.Println("\\evensidemargin -.5cm")

	fmt.Println("\\begin{document}")
	fmt.Println("\\thispagestyle{empty}")
	fmt.Println("\\pagestyle{empty}")
	//fmt.Println("\\tableofcontents")
	//fmt.Println("\\newpage")
	//fmt.Println("\\begin{landscape}")
	fmt.Println("\\begin{longtable}{|p{2cm}|p{1.4cm}|p{4cm}|p{5cm}|p{4cm}|p{3cm}|}")
	fmt.Println("\\hline")
	fmt.Println("\\textbf{Name}& \\textbf{Version}& \\textbf{Summary}& \\textbf{Description}& \\textbf{URL}& \\textbf{Install Time}\\\\")
	fmt.Println("\\hline")
	fmt.Println("\\endfirsthead")
	fmt.Println("\\hline")
	fmt.Println("\\textbf{Name}& \\textbf{Version}& \\textbf{Summary}& \\textbf{Description}& \\textbf{URL}& \\textbf{Install Time}\\\\")
	fmt.Println("\\hline")
	fmt.Println("\\endhead")

	//fmt.Println("\\begin{enumerate}")
	for r := range s {
		//fmt.Println("\\section{" + escapeLatex(rpmInfo[s[r]].Name) + "}")
		//fmt.Println("\\item{" + escapeLatex(rpmInfo[s[r]].Name) + "}")
		//fmt.Println("\\begin{itemize}")
		//for k,v := range rpmInfo[s[r]].Tags{

		//	v = strings.Replace(v, "\n", " ", -1)
		//fmt.Println("\\item {\\bf" + escapeLatex("  " + k + ": ") + "}" + escapeLatex(v))
		//fmt.Println("\\newline")
		//	fmt.Println("\\hline")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["name"]) + "&")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["version"]) + "&")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["summary"]) + "&")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["description"]) + "&")
		fmt.Println("\\url{" + escapeLatex(rpmInfo[s[r]].Tags["url"]) + "}&")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["installtime"]))
		fmt.Println("\\\\ \\hline")
	}
	//fmt.Println("\\end{itemize}")
	//fmt.Println("\\end{section}")
	fmt.Println("\\end{longtable}")
	//fmt.Println("\\end{landscape}")
	fmt.Println("\\end{document}")
}

func escapeLatex(v string) string{
	v = strings.Replace(v, "\\", "\\textbackslash{}", -1)
	v = strings.Replace(v, "_", "\\_", -1)
	v = strings.Replace(v, "$", "\\$", -1)

	v = strings.Replace(v, "#", "\\#", -1)
	v = strings.Replace(v, "%", "\\%", -1)
	v = strings.Replace(v, "^", "\\^{}", -1)
	v = strings.Replace(v, "&", "\\&", -1)

	v = strings.Replace(v, "{", "\\{", -1)

	v = strings.Replace(v, "}", "\\}", -1)
	v = strings.Replace(v, "~", "\\~{}", -1)

	return v
	}
<commit_msg>Improved LaTeX output<commit_after>package main

import(
	"fmt"
	"strings"
)

type LaTeXOut struct{

}

func (lo LaTeXOut) output(s []string, rpmInfo map[string] *RpmInfo) {
	fmt.Println("\\documentclass[11pt,landscape]{article}")
	fmt.Println("")
	fmt.Println("\\usepackage[landscape,paperwidth=10in,paperheight=8.5in]{geometry}")
	fmt.Println("\\usepackage{longtable,microtype,savetrees}")
	fmt.Println("\\usepackage[hyphens]{url}")
	fmt.Println("\\usepackage{seqsplit}")

	fmt.Println("")
	fmt.Println("\\oddsidemargin -.5cm")
	fmt.Println("\\evensidemargin -.5cm")
	fmt.Println("")
	fmt.Println("\\newcommand\\foo[2]{%")
	fmt.Println("\\begin{minipage}{#1}")
	fmt.Println("\\seqsplit{#2}")
	fmt.Println("\\end{minipage}")
	fmt.Println("}")
	fmt.Println("")
	fmt.Println("")
	fmt.Println("\\begin{document}")
	fmt.Println("\\thispagestyle{empty}")
	fmt.Println("\\pagestyle{empty}")
	//fmt.Println("\\tableofcontents")
	//fmt.Println("\\newpage")
	//fmt.Println("\\begin{landscape}")
	fmt.Println("\\begin{longtable}{|p{2cm}|p{1.4cm}|p{4cm}|p{5cm}|p{4cm}|p{3cm}|}")
	fmt.Println("\\hline")
	fmt.Println("\\textbf{Name}& \\textbf{Version}& \\textbf{Summary}& \\textbf{Description}& \\textbf{URL}& \\textbf{Install Time}\\\\")
	fmt.Println("\\hline")
	fmt.Println("\\endfirsthead")
	fmt.Println("\\hline")
	fmt.Println("\\textbf{Name}& \\textbf{Version}& \\textbf{Summary}& \\textbf{Description}& \\textbf{URL}& \\textbf{Install Time}\\\\")
	fmt.Println("\\hline")
	fmt.Println("\\endhead")

	//fmt.Println("\\begin{enumerate}")
	for r := range s {
		//fmt.Println("\\section{" + escapeLatex(rpmInfo[s[r]].Name) + "}")
		//fmt.Println("\\item{" + escapeLatex(rpmInfo[s[r]].Name) + "}")
		//fmt.Println("\\begin{itemize}")
		//for k,v := range rpmInfo[s[r]].Tags{

		//	v = strings.Replace(v, "\n", " ", -1)
		//fmt.Println("\\item {\\bf" + escapeLatex("  " + k + ": ") + "}" + escapeLatex(v))
		//fmt.Println("\\newline")
		//	fmt.Println("\\hline")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["name"]) + "&")
		fmt.Println("\\foo{1.4cm}{" + escapeLatex(rpmInfo[s[r]].Tags["version"]) + "}&")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["summary"]) + "&")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["description"]) + "&")
		fmt.Println("\\url{" + escapeLatex(rpmInfo[s[r]].Tags["url"]) + "}&")
		fmt.Println(escapeLatex(rpmInfo[s[r]].Tags["installtime"]))
		fmt.Println("\\\\ \\hline")
	}
	//fmt.Println("\\end{itemize}")
	//fmt.Println("\\end{section}")
	fmt.Println("\\end{longtable}")
	//fmt.Println("\\end{landscape}")
	fmt.Println("\\end{document}")
}

func escapeLatex(v string) string{
	v = strings.Replace(v, "\\", "\\textbackslash{}", -1)
	v = strings.Replace(v, "_", "\\_", -1)
	v = strings.Replace(v, "$", "\\$", -1)

	v = strings.Replace(v, "#", "\\#", -1)
	v = strings.Replace(v, "%", "\\%", -1)
	v = strings.Replace(v, "^", "\\^{}", -1)
	v = strings.Replace(v, "&", "\\&", -1)

	v = strings.Replace(v, "{", "\\{", -1)

	v = strings.Replace(v, "}", "\\}", -1)
	v = strings.Replace(v, "~", "\\~{}", -1)

	return v
	}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/mr-tron/base58/base58"
)

func main() {

	exampleBase58Encoded := []string{
		"1QCaxc8hutpdZ62iKZsn1TCG3nh7uPZojq",
		"1DhRmSGnhPjUaVPAj48zgPV9e2oRhAQFUb",
		"17LN2oPYRYsXS9TdYdXCCDvF2FegshLDU2",
		"14h2bDLZSuvRFhUL45VjPHJcW667mmRAAn",
	}

	// If a base58 string is on the command line, then use that instead of the 4 exampels above.
	if len(os.Args) > 1 {
		exampleBase58Encoded = os.Args[1:]
	}

	for _, vv := range exampleBase58Encoded {
		num, err := base58.Decode(vv)
		if err != nil {
			fmt.Printf("Demo %d, got error %s\n", vv, err)
			continue
		}
		chk := base58.Encode(num)
		if vv == string(chk) {
			fmt.Printf("Successfully decoded then re-encoded %s\n", vv)
		} else {
			fmt.Printf("Failed on %s\n", vv)
		}
	}
}
<commit_msg>Update cli.go<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/mr-tron/base58/base58"
)

func main() {

	exampleBase58Encoded := []string{
		"1QCaxc8hutpdZ62iKZsn1TCG3nh7uPZojq",
		"1DhRmSGnhPjUaVPAj48zgPV9e2oRhAQFUb",
		"17LN2oPYRYsXS9TdYdXCCDvF2FegshLDU2",
		"14h2bDLZSuvRFhUL45VjPHJcW667mmRAAn",
	}

	// If a base58 string is on the command line, then use that instead of the 4 exampels above.
	if len(os.Args) > 1 {
		exampleBase58Encoded = os.Args[1:]
	}

	for _, vv := range exampleBase58Encoded {
		num, err := base58.Decode(vv)
		if err != nil {
			fmt.Printf("Demo %s, got error %s\n", vv, err)
			continue
		}
		chk := base58.Encode(num)
		if vv == string(chk) {
			fmt.Printf("Successfully decoded then re-encoded %s\n", vv)
		} else {
			fmt.Printf("Failed on %s\n", vv)
		}
	}
}
<|endoftext|>


<commit_before>package lfs

import (
	"crypto/tls"
	"fmt"
	"github.com/rubyist/tracerx"
	"io"
	"net/http"
	"os"
	"strings"
)

func DoHTTP(c *Configuration, req *http.Request) (*http.Response, error) {
	var res *http.Response
	var err error

	traceHttpRequest(c, req)

	switch req.Method {
	case "GET", "HEAD":
		res, err = c.RedirectingHttpClient().Do(req)
	default:
		res, err = c.HttpClient().Do(req)
	}

	traceHttpResponse(c, res)

	return res, err
}

func (c *Configuration) HttpClient() *http.Client {
	if c.httpClient == nil {
		c.httpClient = &http.Client{
			Transport: c.RedirectingHttpClient().Transport,
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				return RedirectError
			},
		}
	}
	return c.httpClient
}

func (c *Configuration) RedirectingHttpClient() *http.Client {
	if c.redirectingHttpClient == nil {
		tr := &http.Transport{}
		sslVerify, _ := c.GitConfig("http.sslverify")
		if sslVerify == "false" || len(os.Getenv("GIT_SSL_NO_VERIFY")) > 0 {
			tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
		}
		c.redirectingHttpClient = &http.Client{Transport: tr}
	}
	return c.redirectingHttpClient
}

var tracedTypes = []string{"json", "text", "xml", "html"}

func traceHttpRequest(c *Configuration, req *http.Request) {
	tracerx.Printf("HTTP: %s %s", req.Method, req.URL.String())

	if c.isTracingHttp == false {
		return
	}

	if req.Body != nil {
		req.Body = newCountedRequest(req)
	}

	fmt.Fprintf(os.Stderr, "> %s %s %s\n", req.Method, req.URL.RequestURI(), req.Proto)
	for key, _ := range req.Header {
		fmt.Fprintf(os.Stderr, "> %s: %s\n", key, req.Header.Get(key))
	}
}

func traceHttpResponse(c *Configuration, res *http.Response) {
	tracerx.Printf("HTTP: %d", res.StatusCode)

	if c.isTracingHttp == false {
		return
	}

	fmt.Fprintf(os.Stderr, "\n")
	fmt.Fprintf(os.Stderr, "< %s %s\n", res.Proto, res.Status)
	for key, _ := range res.Header {
		fmt.Fprintf(os.Stderr, "< %s: %s\n", key, res.Header.Get(key))
	}

	traceBody := false
	ctype := strings.ToLower(strings.SplitN(res.Header.Get("Content-Type"), ";", 2)[0])
	for _, tracedType := range tracedTypes {
		if strings.Contains(ctype, tracedType) {
			traceBody = true
		}
	}

	res.Body = newCountedResponse(res)
	if traceBody {
		res.Body = newTracedBody(res.Body)
	}

	fmt.Fprintf(os.Stderr, "\n")
}

const (
	countingUpload = iota
	countingDownload
)

type countingBody struct {
	Direction int
	Size      int64
	io.ReadCloser
}

func (r *countingBody) Read(p []byte) (int, error) {
	n, err := r.ReadCloser.Read(p)
	r.Size += int64(n)
	return n, err
}

func (r *countingBody) Close() error {
	if r.Direction == countingUpload {
		fmt.Fprintf(os.Stderr, "* uploaded %d bytes\n", r.Size)
	} else {
		fmt.Fprintf(os.Stderr, "* downloaded %d bytes\n", r.Size)
	}
	return r.ReadCloser.Close()
}

func newCountedResponse(res *http.Response) *countingBody {
	return &countingBody{countingDownload, 0, res.Body}
}

func newCountedRequest(req *http.Request) *countingBody {
	return &countingBody{countingUpload, 0, req.Body}
}

type tracedBody struct {
	io.ReadCloser
}

func (r *tracedBody) Read(p []byte) (int, error) {
	n, err := r.ReadCloser.Read(p)
	fmt.Fprintf(os.Stderr, "%s\n", string(p[0:n]))
	return n, err
}

func (r *tracedBody) Close() error {
	return r.ReadCloser.Close()
}

func newTracedBody(body io.ReadCloser) *tracedBody {
	return &tracedBody{body}
}
<commit_msg>we don't need a non-redirecting http client anymore<commit_after>package lfs

import (
	"crypto/tls"
	"fmt"
	"github.com/rubyist/tracerx"
	"io"
	"net/http"
	"os"
	"strings"
)

func DoHTTP(c *Configuration, req *http.Request) (*http.Response, error) {
	traceHttpRequest(c, req)
	res, err := c.HttpClient().Do(req)
	traceHttpResponse(c, res)
	return res, err
}

func (c *Configuration) HttpClient() *http.Client {
	if c.httpClient == nil {
		tr := &http.Transport{}
		sslVerify, _ := c.GitConfig("http.sslverify")
		if sslVerify == "false" || len(os.Getenv("GIT_SSL_NO_VERIFY")) > 0 {
			tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
		}
		c.httpClient = &http.Client{Transport: tr}
	}
	return c.httpClient
}

var tracedTypes = []string{"json", "text", "xml", "html"}

func traceHttpRequest(c *Configuration, req *http.Request) {
	tracerx.Printf("HTTP: %s %s", req.Method, req.URL.String())

	if c.isTracingHttp == false {
		return
	}

	if req.Body != nil {
		req.Body = newCountedRequest(req)
	}

	fmt.Fprintf(os.Stderr, "> %s %s %s\n", req.Method, req.URL.RequestURI(), req.Proto)
	for key, _ := range req.Header {
		fmt.Fprintf(os.Stderr, "> %s: %s\n", key, req.Header.Get(key))
	}
}

func traceHttpResponse(c *Configuration, res *http.Response) {
	tracerx.Printf("HTTP: %d", res.StatusCode)

	if c.isTracingHttp == false {
		return
	}

	fmt.Fprintf(os.Stderr, "\n")
	fmt.Fprintf(os.Stderr, "< %s %s\n", res.Proto, res.Status)
	for key, _ := range res.Header {
		fmt.Fprintf(os.Stderr, "< %s: %s\n", key, res.Header.Get(key))
	}

	traceBody := false
	ctype := strings.ToLower(strings.SplitN(res.Header.Get("Content-Type"), ";", 2)[0])
	for _, tracedType := range tracedTypes {
		if strings.Contains(ctype, tracedType) {
			traceBody = true
		}
	}

	res.Body = newCountedResponse(res)
	if traceBody {
		res.Body = newTracedBody(res.Body)
	}

	fmt.Fprintf(os.Stderr, "\n")
}

const (
	countingUpload = iota
	countingDownload
)

type countingBody struct {
	Direction int
	Size      int64
	io.ReadCloser
}

func (r *countingBody) Read(p []byte) (int, error) {
	n, err := r.ReadCloser.Read(p)
	r.Size += int64(n)
	return n, err
}

func (r *countingBody) Close() error {
	if r.Direction == countingUpload {
		fmt.Fprintf(os.Stderr, "* uploaded %d bytes\n", r.Size)
	} else {
		fmt.Fprintf(os.Stderr, "* downloaded %d bytes\n", r.Size)
	}
	return r.ReadCloser.Close()
}

func newCountedResponse(res *http.Response) *countingBody {
	return &countingBody{countingDownload, 0, res.Body}
}

func newCountedRequest(req *http.Request) *countingBody {
	return &countingBody{countingUpload, 0, req.Body}
}

type tracedBody struct {
	io.ReadCloser
}

func (r *tracedBody) Read(p []byte) (int, error) {
	n, err := r.ReadCloser.Read(p)
	fmt.Fprintf(os.Stderr, "%s\n", string(p[0:n]))
	return n, err
}

func (r *tracedBody) Close() error {
	return r.ReadCloser.Close()
}

func newTracedBody(body io.ReadCloser) *tracedBody {
	return &tracedBody{body}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/hex"
)

type HCID []byte

func (hcid HCID) Hex() string {
	return hex.EncodeToString(hcid)
}

func (hcid HCID) Bytes() []byte {
	return hcid
}

type HKID []byte

func (hkid HKID) Hex() string {
	return hex.EncodeToString(hkid)
}

func (hkid HKID) Bytes() []byte {
	return hkid
}

func (hkid HKID) String() string {
	return hkid.Hex()
}

func HkidFromHex(s string) (HKID, error) {
	dabytes, err := hex.DecodeString(s)
	if err == nil {
		return HKID(dabytes), err
	}
	return nil, err
}

func (hcid HCID) String() string {
	return hcid.Hex()
}

type HID interface {
	Byteser
	Hexer
}
type Byteser interface {
	Bytes() []byte
}

type Hexer interface {
	Hex() string
}
<commit_msg>added ability to make an HCID form the hexString form<commit_after>package main

import (
	"encoding/hex"
)

type HCID []byte

func (hcid HCID) Hex() string {
	return hex.EncodeToString(hcid)
}

func (hcid HCID) Bytes() []byte {
	return hcid
}

type HKID []byte

func (hkid HKID) Hex() string {
	return hex.EncodeToString(hkid)
}

func (hkid HKID) Bytes() []byte {
	return hkid
}

func (hkid HKID) String() string {
	return hkid.Hex()
}

func HkidFromHex(s string) (HKID, error) {
	dabytes, err := hex.DecodeString(s)
	if err == nil {
		return HKID(dabytes), err
	}
	return nil, err
}

func HcidFromHex(s string) (HCID, error) {
	dabytes, err := hex.DecodeString(s)
	if err == nil {
		return HCID(dabytes), err
	}
	return nil, err
}

func (hcid HCID) String() string {
	return hcid.Hex()
}

type HID interface {
	Byteser
	Hexer
}
type Byteser interface {
	Bytes() []byte
}

type Hexer interface {
	Hex() string
}
<|endoftext|>


<commit_before>// The gohaml package contains a HAML parser similar to the one found at http://www.haml-lang.com.
//
//You can find the specifics about this implementation at http://github.com/realistschuckle/gohaml.
package gohaml

import (
)

/*
Engine provides the template interpretation functionality to convert a HAML template into its
corresponding tag-based representation.

Available options are:
  engine.Options["autoclose"] = true|false, default true

The Options field contains the values to modify the way that the engine produces the markup.

The Indentation field contains the string used by the engine to perform indentation.

The IncludeCallback field contains the callback invoked by the gohaml engine to process other files
included through the %include extension.
*/
type Engine struct {
	Autoclose bool
	Indentation string
	IncludeCallback func(string, map[string]interface{}) string
	ast *tree
}

// NewEngine returns a new Engine with the given input.
func NewEngine(input string) (engine *Engine) {
	engine = &Engine{true, "\t", nil, parser.parse(input)}
	return
}

func (self *Engine) Render(scope map[string]interface{}) (output string) {
	output = self.ast.resolve(scope, self.Indentation, self.Autoclose)
	return
}
<commit_msg>Added documentation comment to the Engine#Render method.<commit_after>// The gohaml package contains a HAML parser similar to the one found at http://www.haml-lang.com.
//
//You can find the specifics about this implementation at http://github.com/realistschuckle/gohaml.
package gohaml

import (
)

/*
Engine provides the template interpretation functionality to convert a HAML template into its
corresponding tag-based representation.

Available options are:
  engine.Options["autoclose"] = true|false, default true

The Options field contains the values to modify the way that the engine produces the markup.

The Indentation field contains the string used by the engine to perform indentation.

The IncludeCallback field contains the callback invoked by the gohaml engine to process other files
included through the %include extension.
*/
type Engine struct {
	Autoclose bool
	Indentation string
	IncludeCallback func(string, map[string]interface{}) string
	ast *tree
}

// NewEngine returns a new Engine with the given input.
func NewEngine(input string) (engine *Engine) {
	engine = &Engine{true, "\t", nil, parser.parse(input)}
	return
}

// Render interprets the HAML supplied to the NewEngine method.
func (self *Engine) Render(scope map[string]interface{}) (output string) {
	output = self.ast.resolve(scope, self.Indentation, self.Autoclose)
	return
}
<|endoftext|>


<commit_before>package cloudflare

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/pkg/errors"
)

// FallbackDomainResponse represents the response from the get fallback
// domain endpoints.
type FallbackDomainResponse struct {
	Response
	Result []FallbackDomain `json:"result"`
}

// FallbackDomain represents the individual domain struct.
type FallbackDomain struct {
	Suffix      string   `json:"suffix,omitempty"`
	Description string   `json:"description,omitempty"`
	DNSServer   []string `json:"dns_server,omitempty"`
}

// ListFallbackDomains returns all fallback domains within an account.
//
// API reference: https://api.cloudflare.com/#devices-get-local-domain-fallback-list
func (api *API) ListFallbackDomains(ctx context.Context, accountID string) ([]FallbackDomain, error) {
	uri := fmt.Sprintf("/%s/%s/devices/policy/fallback_domains", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return []FallbackDomain{}, err
	}

	var fallbackDomainResponse FallbackDomainResponse
	err = json.Unmarshal(res, &fallbackDomainResponse)
	if err != nil {
		return []FallbackDomain{}, errors.Wrap(err, errUnmarshalError)
	}

	return fallbackDomainResponse.Result, nil
}

// UpdateFallbackDomain updates the existing fallback domain policy.
//
// API reference: https://api.cloudflare.com/#devices-set-local-domain-fallback-list
func (api *API) UpdateFallbackDomain(ctx context.Context, accountID string, domains []FallbackDomain) ([]FallbackDomain, error) {
	uri := fmt.Sprintf("/%s/%s/devices/policy/fallback_domains", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, domains)
	if err != nil {
		return []FallbackDomain{}, err
	}

	var fallbackDomainResponse FallbackDomainResponse
	err = json.Unmarshal(res, &fallbackDomainResponse)
	if err != nil {
		return []FallbackDomain{}, errors.Wrap(err, errUnmarshalError)
	}

	return fallbackDomainResponse.Result, nil
}
<commit_msg>fallback_domain: add ability to restore default domain list<commit_after>package cloudflare

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"

	"github.com/pkg/errors"
)

// FallbackDomainResponse represents the response from the get fallback
// domain endpoints.
type FallbackDomainResponse struct {
	Response
	Result []FallbackDomain `json:"result"`
}

// FallbackDomain represents the individual domain struct.
type FallbackDomain struct {
	Suffix      string   `json:"suffix,omitempty"`
	Description string   `json:"description,omitempty"`
	DNSServer   []string `json:"dns_server,omitempty"`
}

// ListFallbackDomains returns all fallback domains within an account.
//
// API reference: https://api.cloudflare.com/#devices-get-local-domain-fallback-list
func (api *API) ListFallbackDomains(ctx context.Context, accountID string) ([]FallbackDomain, error) {
	uri := fmt.Sprintf("/%s/%s/devices/policy/fallback_domains", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodGet, uri, nil)
	if err != nil {
		return []FallbackDomain{}, err
	}

	var fallbackDomainResponse FallbackDomainResponse
	err = json.Unmarshal(res, &fallbackDomainResponse)
	if err != nil {
		return []FallbackDomain{}, errors.Wrap(err, errUnmarshalError)
	}

	return fallbackDomainResponse.Result, nil
}

// UpdateFallbackDomain updates the existing fallback domain policy.
//
// API reference: https://api.cloudflare.com/#devices-set-local-domain-fallback-list
func (api *API) UpdateFallbackDomain(ctx context.Context, accountID string, domains []FallbackDomain) ([]FallbackDomain, error) {
	uri := fmt.Sprintf("/%s/%s/devices/policy/fallback_domains", AccountRouteRoot, accountID)

	res, err := api.makeRequestContext(ctx, http.MethodPut, uri, domains)
	if err != nil {
		return []FallbackDomain{}, err
	}

	var fallbackDomainResponse FallbackDomainResponse
	err = json.Unmarshal(res, &fallbackDomainResponse)
	if err != nil {
		return []FallbackDomain{}, errors.Wrap(err, errUnmarshalError)
	}

	return fallbackDomainResponse.Result, nil
}

// RestoreFallbackDomainDefaults resets the domain fallback values to the default
// list.
//
// API reference: TBA.
func (api *API) RestoreFallbackDomainDefaults(ctx context.Context, accountID string) error {
	uri := fmt.Sprintf("/%s/%s/devices/policy/fallback_domains?reset_defaults=true", AccountRouteRoot, accountID)

	_, err := api.makeRequestContext(ctx, http.MethodDelete, uri, []string{})
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>