<commit_before>package storage

type multiIterator struct {
	current int
	iters   []Iterator
}

// NewMultiIterator returns an iterator that iterates over the given iterators.
func NewMultiIterator(iters []Iterator) Iterator {
	if len(iters) == 0 {
		return &NullIter{}
	}

	return &multiIterator{current: 0, iters: iters}
}

func (m *multiIterator) Next() (next bool) {
	for ; m.current < len(m.iters); m.current++ {
		next = m.iters[m.current].Next()
		if next {
			break
		}
		m.current++
	}

	return next
}

func (m *multiIterator) Key() []byte {
	return m.iters[m.current].Key()
}

func (m *multiIterator) Value() ([]byte, error) {
	return m.iters[m.current].Value()
}

func (m *multiIterator) Release() {
	for i := range m.iters {
		m.iters[i].Release()
	}
	m.current = 0
	m.iters = []Iterator{&NullIter{}}
}

func (m *multiIterator) Seek(key []byte) bool {
	m.current = 0
	iters := []Iterator{}
	ok := false
	for i := range m.iters {
		if m.iters[i].Seek(key) {
			iters = append(iters, m.iters[i])
			ok = true
		}
	}
	return ok
}
<commit_msg>oops, don't increment twice in the same loop<commit_after>package storage

type multiIterator struct {
	current int
	iters   []Iterator
}

// NewMultiIterator returns an iterator that iterates over the given iterators.
func NewMultiIterator(iters []Iterator) Iterator {
	if len(iters) == 0 {
		return &NullIter{}
	}

	return &multiIterator{current: 0, iters: iters}
}

func (m *multiIterator) Next() (next bool) {
	for ; m.current < len(m.iters); m.current++ {
		next = m.iters[m.current].Next()
		if next {
			break
		}
	}
	return next
}

func (m *multiIterator) Key() []byte {
	return m.iters[m.current].Key()
}

func (m *multiIterator) Value() ([]byte, error) {
	return m.iters[m.current].Value()
}

func (m *multiIterator) Release() {
	for i := range m.iters {
		m.iters[i].Release()
	}
	m.current = 0
	m.iters = []Iterator{&NullIter{}}
}

func (m *multiIterator) Seek(key []byte) bool {
	m.current = 0
	iters := []Iterator{}
	ok := false
	for i := range m.iters {
		if m.iters[i].Seek(key) {
			iters = append(iters, m.iters[i])
			ok = true
		}
	}
	return ok
}
<|endoftext|>


<commit_before>package etcdstore

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/bobbytables/gangway/data"
	"golang.org/x/net/context"

	"github.com/coreos/etcd/client"
)

var (
	// GangwayKeyPrefix is the etcd key prefix
	GangwayKeyPrefix = "/gangway"

	// GangwayDefinitionsKey is the etcd key for all definitions
	GangwayDefinitionsKey = fmt.Sprintf("%s/%s", GangwayKeyPrefix, "definitions")
)

// RetrieveDefinitions implements store.Store
func (s *Store) RetrieveDefinitions() ([]data.Definition, error) {
	kapp := s.newKeysAPIFactory(s.etcdClient)
	resp, err := kapp.Get(context.TODO(), GangwayDefinitionsKey, &client.GetOptions{Recursive: true})
	if err != nil {
		return nil, err
	}

	var ds []data.Definition
	for _, node := range resp.Node.Nodes {
		label := strings.TrimPrefix(node.Key, GangwayDefinitionsKey+"/")
		jsonV := node.Value
		d := data.Definition{Label: label}

		if err := json.NewDecoder(strings.NewReader(jsonV)).Decode(&d); err != nil {
			return nil, err
		}

		ds = append(ds, d)
	}

	return ds, nil
}

// AddDefinition implements store.Store
func (s *Store) AddDefinition(d data.Definition) error {
	kapp := s.newKeysAPIFactory(s.etcdClient)

	js, err := json.Marshal(d)
	if err != nil {
		return err
	}

	key := fmt.Sprintf("%s/%s", GangwayDefinitionsKey, d.Label)
	_, err = kapp.Set(context.TODO(), key, string(js), nil)

	return err
}
<commit_msg>Refactor node to definition code.<commit_after>package etcdstore

import (
	"encoding/json"
	"fmt"
	"strings"

	"github.com/bobbytables/gangway/data"
	"golang.org/x/net/context"

	"github.com/coreos/etcd/client"
)

var (
	// GangwayKeyPrefix is the etcd key prefix
	GangwayKeyPrefix = "/gangway"

	// GangwayDefinitionsKey is the etcd key for all definitions
	GangwayDefinitionsKey = fmt.Sprintf("%s/%s", GangwayKeyPrefix, "definitions")
)

// RetrieveDefinitions implements store.Store
func (s *Store) RetrieveDefinitions() ([]data.Definition, error) {
	kapp := s.newKeysAPIFactory(s.etcdClient)
	resp, err := kapp.Get(context.TODO(), GangwayDefinitionsKey, &client.GetOptions{Recursive: true})
	if err != nil {
		return nil, err
	}

	var ds []data.Definition
	for _, node := range resp.Node.Nodes {
		d, err := definitionFromNode(node)
		if err != nil {
			return nil, err
		}

		ds = append(ds, d)
	}

	return ds, nil
}

// AddDefinition implements store.Store
func (s *Store) AddDefinition(d data.Definition) error {
	kapp := s.newKeysAPIFactory(s.etcdClient)

	js, err := json.Marshal(d)
	if err != nil {
		return err
	}

	key := fmt.Sprintf("%s/%s", GangwayDefinitionsKey, d.Label)
	_, err = kapp.Set(context.TODO(), key, string(js), nil)

	return err
}

func definitionFromNode(n *client.Node) (data.Definition, error) {
	label := strings.TrimPrefix(n.Key, GangwayDefinitionsKey+"/")
	jsonV := n.Value
	d := data.Definition{Label: label}

	if err := json.NewDecoder(strings.NewReader(jsonV)).Decode(&d); err != nil {
		return data.Definition{}, err
	}

	return d, nil
}
<|endoftext|>


<commit_before>// This file is autogenerated, see tools/release/version.go

package libkbfs

// Version is the current version (should be MAJOR.MINOR.PATCH)
const Version = "1.0.0"

// DefaultBuild is the current build number
const DefaultBuild = "32"
<commit_msg>Version file is not auto generated anymore<commit_after>package libkbfs

// Version is the current version (should be MAJOR.MINOR.PATCH)
const Version = "1.0.0"

// DefaultBuild is the current build number
const DefaultBuild = "32"
<|endoftext|>


<commit_before>package main

import (
	"os"
	"strings"
	"testing"

	"../../gff3"
)

var fakeGff3Line = "chr1\tHAVANA\tgene\t11869\t14409\t.\t+\t.\tID=ENSG00000223972.5;gene_id=ENSG00000223972.5;gene_type=transcribed_unprocessed_pseudogene;gene_status=KNOWN;gene_name=DDX11L1;level=2;havana_gene=OTTHUMG00000000961.2"

func TestSimpleParseLineWithReader(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	if myRecord, err := myReader.Read(); err != nil {
		t.Errorf("record was not correctly parsed and returned an error")
	} else if !myRecord.Complete {
		t.Errorf("record was not correctly parsed, but did not throw an error")
	}
}

func TestParseTwoLinesWithReader(t *testing.T) {
	fakeGff3Line := "chr1\tHAVANA\tgene\t11869\t14409\t.\t+\t.\tID=ENSG00000223972.5;gene_id=ENSG00000223972.5;gene_type=transcribed_unprocessed_pseudogene;gene_status=KNOWN;gene_name=DDX11L1;level=2;havana_gene=OTTHUMG00000000961.2\nchr1\tHAVANA\tgene\t69091\t70008\t.\t+\t.\tID=ENSG00000186092.4;gene_id=ENSG00000186092.4;gene_type=protein_coding;gene_status=KNOWN;gene_name=OR4F5;level=2;havana_gene=OTTHUMG00000001094.2"
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	if myRecord, err := myReader.Read(); err != nil {
		t.Errorf("first record was not correctly parsed and returned an error")
	} else if !myRecord.Complete {
		t.Errorf("first record was not correctly parsed, but did not throw an error")
	}
	if myRecord, err := myReader.Read(); err != nil {
		t.Errorf("second record was not correctly parsed and returned an error")
	} else if !myRecord.Complete {
		t.Errorf("second record was not correctly parsed, but did not throw an error")
	}
}

func TestParseSeveralCommentsBeforeLine(t *testing.T) {
	fakeGff3Line := "#GFF3 file\n#header information\n#file version\nchr1\tHAVANA\tgene\t11869\t14409\t.\t+\t.\tID=ENSG00000223972.5;gene_id=ENSG00000223972.5;gene_type=transcribed_unprocessed_pseudogene;gene_status=KNOWN;gene_name=DDX11L1;level=2;havana_gene=OTTHUMG00000000961.2"
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	if myRecord, err := myReader.Read(); err != nil {
		t.Errorf("record was not correctly parsed and returned an error")
	} else if !myRecord.Complete {
		t.Errorf("record was not correctly parsed, but did not throw an error")
	}
}

func TestRecordFilterStrand(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	myRecord, _ := myReader.Read()
	filtRecord := myRecord.FilterByField("strand", "+")
	if !filtRecord.Complete {
		t.Errorf("record did not successfully pass filter")
	}
	filtRecord = myRecord.FilterByField("strand", "-")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail filter")
	}
}

func TestRecordFilterAttribute(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	myRecord, _ := myReader.Read()
	filtRecord := myRecord.FilterByAttribute("level", "2")
	if !filtRecord.Complete {
		t.Errorf("record did not successfully pass filter")
	}
	filtRecord = myRecord.FilterByAttribute("gene", "GAPDH")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail fitler")
	}
}

func TestChainedRecordFilters(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	myRecord, _ := myReader.Read()
	filtRecord := myRecord.FilterByAttribute("level", "2").FilterByField("strand", "+").FilterByField("type", "gene")
	if !filtRecord.Complete {
		t.Errorf("record did not successfully pass filter")
	}
	filtRecord = myRecord.FilterByAttribute("level", "2").FilterByField("strand", "+").FilterByField("type", "exon")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail filter")
	}
	filtRecord = myRecord.FilterByAttribute("level", "2").FilterByField("strand", "-").FilterByField("type", "gene")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail filter")
	}
}

func TestMain(m *testing.M) {
	os.Exit(m.Run())
}
<commit_msg>more thorough test of record parse, implementing deep comparison<commit_after>package main

import (
	"os"
	"reflect"
	"strings"
	"testing"

	"../../gff3"
)

var fakeGff3Line = "chr1\tHAVANA\tgene\t11869\t14409\t.\t+\t.\tID=ENSG00000223972.5;gene_id=ENSG00000223972.5;gene_type=transcribed_unprocessed_pseudogene;gene_status=KNOWN;gene_name=DDX11L1;level=2;havana_gene=OTTHUMG00000000961.2"

func TestSimpleParseLineWithReader(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	myRecord, err := myReader.Read()
	if err != nil {
		t.Errorf("record was not correctly parsed and returned an error")
	}
	// file opened fine, but is the content correct?
	var fakeGff3Solution = gff3.Record{
		Complete:    true,
		SeqidField:  "chr1",
		SourceField: "HAVANA",
		TypeField:   "gene",
		StartField:  11869,
		EndField:    14409,
		ScoreField:  0,
		StrandField: '+',
		PhaseField:  0,
		AttributesField: map[string]string{
			"ID":          "ENSG00000223972.5",
			"gene_id":     "ENSG00000223972.5",
			"gene_type":   "transcribed_unprocessed_pseudogene",
			"gene_status": "KNOWN",
			"gene_name":   "DDX11L1",
			"level":       "2",
			"havana_gene": "OTTHUMG00000000961.2",
		},
	}
	// deep equal will recursively compare all attributes and values of the structs
	// a simple equal "==" doesn't suffice because keys in the attributes map may be reordered
	if !reflect.DeepEqual(myRecord, &fakeGff3Solution) {
		t.Errorf("record was not correctly parsed, but did not throw an error")
	}
	fakeGff3Solution.StartField = 1
	if reflect.DeepEqual(myRecord, &fakeGff3Solution) {
		t.Errorf("records are different and should not be equal")
	}

}

func TestParseTwoLinesWithReader(t *testing.T) {
	fakeGff3Line := "chr1\tHAVANA\tgene\t11869\t14409\t.\t+\t.\tID=ENSG00000223972.5;gene_id=ENSG00000223972.5;gene_type=transcribed_unprocessed_pseudogene;gene_status=KNOWN;gene_name=DDX11L1;level=2;havana_gene=OTTHUMG00000000961.2\nchr1\tHAVANA\tgene\t69091\t70008\t.\t+\t.\tID=ENSG00000186092.4;gene_id=ENSG00000186092.4;gene_type=protein_coding;gene_status=KNOWN;gene_name=OR4F5;level=2;havana_gene=OTTHUMG00000001094.2"
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	if myRecord, err := myReader.Read(); err != nil {
		t.Errorf("first record was not correctly parsed and returned an error")
	} else if !myRecord.Complete {
		t.Errorf("first record was not correctly parsed, but did not throw an error")
	}
	if myRecord, err := myReader.Read(); err != nil {
		t.Errorf("second record was not correctly parsed and returned an error")
	} else if !myRecord.Complete {
		t.Errorf("second record was not correctly parsed, but did not throw an error")
	}
}

func TestParseSeveralCommentsBeforeLine(t *testing.T) {
	fakeGff3Line := "#GFF3 file\n#header information\n#file version\nchr1\tHAVANA\tgene\t11869\t14409\t.\t+\t.\tID=ENSG00000223972.5;gene_id=ENSG00000223972.5;gene_type=transcribed_unprocessed_pseudogene;gene_status=KNOWN;gene_name=DDX11L1;level=2;havana_gene=OTTHUMG00000000961.2"
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	if myRecord, err := myReader.Read(); err != nil {
		t.Errorf("record was not correctly parsed and returned an error")
	} else if !myRecord.Complete {
		t.Errorf("record was not correctly parsed, but did not throw an error")
	}
}

func TestRecordFilterStrand(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	myRecord, _ := myReader.Read()
	filtRecord := myRecord.FilterByField("strand", "+")
	if !filtRecord.Complete {
		t.Errorf("record did not successfully pass filter")
	}
	filtRecord = myRecord.FilterByField("strand", "-")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail filter")
	}
}

func TestRecordFilterAttribute(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	myRecord, _ := myReader.Read()
	filtRecord := myRecord.FilterByAttribute("level", "2")
	if !filtRecord.Complete {
		t.Errorf("record did not successfully pass filter")
	}
	filtRecord = myRecord.FilterByAttribute("gene", "GAPDH")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail fitler")
	}
}

func TestChainedRecordFilters(t *testing.T) {
	myReader := gff3.NewReader(strings.NewReader(fakeGff3Line))
	myRecord, _ := myReader.Read()
	filtRecord := myRecord.FilterByAttribute("level", "2").FilterByField("strand", "+").FilterByField("type", "gene")
	if !filtRecord.Complete {
		t.Errorf("record did not successfully pass filter")
	}
	filtRecord = myRecord.FilterByAttribute("level", "2").FilterByField("strand", "+").FilterByField("type", "exon")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail filter")
	}
	filtRecord = myRecord.FilterByAttribute("level", "2").FilterByField("strand", "-").FilterByField("type", "gene")
	if filtRecord.Complete {
		t.Errorf("record did not appropriately fail filter")
	}
}

func TestMain(m *testing.M) {
	os.Exit(m.Run())
}
<|endoftext|>


<commit_before>// +build new

package gototo

import (
	"encoding/json"
	zmq "github.com/JeremyOT/gozmq"
	"log"
	"runtime"
)

var registeredWorkerFunctions map[string]WorkerFunction = make(map[string]WorkerFunction)

type WorkerCommand int

const (
	QUIT = WorkerCommand(-1)
)

type WorkerStatus int

const (
	STOPPED = WorkerStatus(0)
	RUNNING = WorkerStatus(1)
)

var logger *log.Logger

func SetLogger(l *log.Logger) {
	logger = l
}

func writeLog(message ...interface{}) {
	if logger != nil {
		logger.Println(message)
	} else {
		println(message)
	}
}

type WorkerFunction func(interface{}) interface{}

func RunRouter(routerAddress, dealerAddress string, routerBind, dealerBind bool) error {
	context, _ := zmq.NewContext()
	defer context.Close()
	router, _ := context.NewSocket(zmq.ROUTER)
	defer router.Close()
	if routerBind {
		router.Bind(routerAddress)
	} else {
		router.Connect(routerAddress)
	}
	dealer, _ := context.NewSocket(zmq.DEALER)
	defer dealer.Close()
	if dealerBind {
		dealer.Bind(dealerAddress)
	} else {
		dealer.Connect(dealerAddress)
	}
	return zmq.Device(zmq.QUEUE, router, dealer)
}

func RegisterWorkerFunction(name string, workerFunction WorkerFunction) {
	registeredWorkerFunctions[name] = workerFunction
}

func RunWorker(address string, control chan WorkerCommand, status chan WorkerStatus) {
	defer func() { status <- STOPPED }()
	context, _ := zmq.NewContext()
	defer context.Close()
	socket, _ := context.NewSocket(zmq.REP)
	defer socket.Close()
	socket.SetSockOptInt(zmq.RCVTIMEO, 100)
	socket.Connect(address)
	status <- RUNNING
	for {
		select {
		case <-control:
			return
		default:
			message, err := socket.RecvMultipart(0)
			if err != nil {
				break
			}
			data := map[string]interface{}{}
			json.Unmarshal(message[len(message)-1], &data)
			if data == nil {
				writeLog("Received invalid message")
				continue
			}
			workerFunction := registeredWorkerFunctions[data["method"].(string)]
			if workerFunction == nil {
				writeLog("Unregistered worker function:", data["method"].(string))
				continue
			}
			response := workerFunction(data["parameters"])
			responseData, _ := json.Marshal(response)
			message[len(message)-1] = responseData
			socket.SendMultipart(message, 0)
		}
	}
}

func StartWorker(address string) (WorkerStatus, chan WorkerCommand, chan WorkerStatus) {
	controlChannel := make(chan WorkerCommand)
	statusChannel := make(chan WorkerStatus)
	go RunWorker(address, controlChannel, statusChannel)
	return <-statusChannel, controlChannel, statusChannel
}

func RunWorkerServer(routerAddress, internalAddress string, routerBind bool, count int) {
	go RunRouter(routerAddress, internalAddress, routerBind, true)
	RunWorkers(internalAddress, count)
}

func RunWorkers(address string, count int) {
	if count <= 0 {
		count = runtime.NumCPU()
	}
	statusChannels := make([]chan WorkerStatus, count)
	for i := 0; i < count; i++ {
		_, _, statusChannel := StartWorker(address)
		statusChannels[i] = statusChannel
	}
	for _, c := range statusChannels {
		<-c
	}
}
<commit_msg>remove IPC socket, run worker methods in goroutines<commit_after>// +build new

package gototo

import (
	"encoding/json"
	zmq "github.com/JeremyOT/gozmq"
	"log"
	"runtime"
)

var registeredWorkerFunctions map[string]WorkerFunction = make(map[string]WorkerFunction)
var activeTimeout = 1
var passiveTimeout = 100

type WorkerCommand int

const (
	QUIT = WorkerCommand(-1)
)

type WorkerStatus int

type WorkerResponse struct {
	message [][]byte
	response interface{}
}

const (
	STOPPED = WorkerStatus(0)
	RUNNING = WorkerStatus(1)
)

var logger *log.Logger

func SetLogger(l *log.Logger) {
	logger = l
}

func writeLog(message ...interface{}) {
	if logger != nil {
		logger.Println(message)
	} else {
		println(message)
	}
}

type WorkerFunction func(interface{}) interface{}

func RunRouter(routerAddress, dealerAddress string, routerBind, dealerBind bool) error {
	context, _ := zmq.NewContext()
	defer context.Close()
	router, _ := context.NewSocket(zmq.ROUTER)
	defer router.Close()
	if routerBind {
		router.Bind(routerAddress)
	} else {
		router.Connect(routerAddress)
	}
	dealer, _ := context.NewSocket(zmq.DEALER)
	defer dealer.Close()
	if dealerBind {
		dealer.Bind(dealerAddress)
	} else {
		dealer.Connect(dealerAddress)
	}
	return zmq.Device(zmq.QUEUE, router, dealer)
}

func RegisterWorkerFunction(name string, workerFunction WorkerFunction) {
	registeredWorkerFunctions[name] = workerFunction
}

func callworker(responseChannel chan *WorkerResponse, message [][]byte, parameters interface{}, workerFunction WorkerFunction) {
	response := workerFunction(parameters)
	responseChannel <- &WorkerResponse {message: message, response: response}
}

func RunWorker(address string, numWorkers int, quit chan int, wait chan int) {
	defer func() { close(wait) }()
	context, _ := zmq.NewContext()
	defer context.Close()
	socket, _ := context.NewSocket(zmq.ROUTER)
	defer socket.Close()
	socket.SetSockOptInt(zmq.RCVTIMEO, passiveTimeout)
	socket.Bind(address)
	runningWorkers := 0
	responseChannel := make(chan *WorkerResponse)
	sendResponse := func(response *WorkerResponse) {
			runningWorkers -= 1
			responseData, _ := json.Marshal(response.response)
			response.message[len(response.message)-1] = responseData
			socket.SendMultipart(response.message, 0)
			if runningWorkers == 0 {
				socket.SetSockOptInt(zmq.RCVTIMEO, passiveTimeout)
			}
	}
	for {
		if runningWorkers == numWorkers {
			select {
				case response := <-responseChannel:
					sendResponse(response)
				case <- quit:
					return
			}
			continue
		}
		select {
		case <- quit:
			return
		case response := <-responseChannel:
			sendResponse(response)
			break
		default:
			message, err := socket.RecvMultipart(0)
			if err != nil {
				break
			}
			data := map[string]interface{}{}
			json.Unmarshal(message[len(message)-1], &data)
			if data == nil {
				writeLog("Received invalid message")
				break
			}
			workerFunction := registeredWorkerFunctions[data["method"].(string)]
			if workerFunction == nil {
				writeLog("Unregistered worker function:", data["method"].(string))
				break
			}
			if runningWorkers == 0 {
				socket.SetSockOptInt(zmq.RCVTIMEO, activeTimeout)
			}
			runningWorkers += 1
			go callworker(responseChannel, message, data["parameters"], workerFunction)
		}
	}
}

func RunWorkerServer(routerAddress, internalAddress string, routerBind bool, count int) {
	if count <= 0 {
		count = runtime.NumCPU()
	}
	quit := make(chan int)
	wait := make(chan int)
	RunWorker(routerAddress, count, quit, wait)
	<-wait
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package xapi

import (
	"io"
	"io/ioutil"

	"github.com/golang/protobuf/proto"
	"github.com/juju/errors"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/mysql"
	"github.com/pingcap/tidb/tablecodec"
	"github.com/pingcap/tidb/terror"
	"github.com/pingcap/tidb/util/codec"
	"github.com/pingcap/tidb/util/types"
	"github.com/pingcap/tipb/go-tipb"
)

var (
	errInvalidResp = terror.ClassXEval.New(codeInvalidResp, "invalid response")
	errNilResp     = terror.ClassXEval.New(codeNilResp, "client returns nil response")
)

var (
	_ SelectResult  = &selectResult{}
	_ PartialResult = &partialResult{}
)

// SelectResult is an iterator of coprocessor partial results.
type SelectResult interface {
	// Next gets the next partial result.
	Next() (PartialResult, error)
	// SetFields sets the expected result type.
	SetFields(fields []*types.FieldType)
	// Close closes the iterator.
	Close() error
}

// PartialResult is the result from a single region server.
type PartialResult interface {
	// Next returns the next row of the sub result.
	// If no more row to return, data would be nil.
	Next() (handle int64, data []types.Datum, err error)
	// Close closes the partial result.
	Close() error
}

// SelectResult is used to get response rows from SelectRequest.
type selectResult struct {
	index     bool
	aggregate bool
	fields    []*types.FieldType
	resp      kv.Response
}

// Next returns the next row.
func (r *selectResult) Next() (pr PartialResult, err error) {
	var reader io.ReadCloser
	reader, err = r.resp.Next()
	if err != nil {
		return nil, errors.Trace(err)
	}
	if reader == nil {
		return nil, nil
	}
	pr = &partialResult{
		index:     r.index,
		fields:    r.fields,
		reader:    reader,
		aggregate: r.aggregate,
	}
	return
}

// SetFields sets select result field types.
func (r *selectResult) SetFields(fields []*types.FieldType) {
	r.fields = fields
}

// Close closes SelectResult.
func (r *selectResult) Close() error {
	return r.resp.Close()
}

// partialResult represents a subset of select result.
type partialResult struct {
	index     bool
	aggregate bool
	fields    []*types.FieldType
	reader    io.ReadCloser
	resp      *tipb.SelectResponse
	cursor    int
}

// Next returns the next row of the sub result.
// If no more row to return, data would be nil.
func (r *partialResult) Next() (handle int64, data []types.Datum, err error) {
	if r.resp == nil {
		r.resp = new(tipb.SelectResponse)
		var b []byte
		b, err = ioutil.ReadAll(r.reader)
		r.reader.Close()
		if err != nil {
			return 0, nil, errors.Trace(err)
		}
		err = proto.Unmarshal(b, r.resp)
		if err != nil {
			return 0, nil, errors.Trace(err)
		}
		if r.resp.Error != nil {
			return 0, nil, errInvalidResp.Gen("[%d %s]", r.resp.Error.GetCode(), r.resp.Error.GetMsg())
		}
	}
	if r.cursor >= len(r.resp.Rows) {
		return 0, nil, nil
	}
	row := r.resp.Rows[r.cursor]
	data, err = tablecodec.DecodeValues(row.Data, r.fields, r.index)
	if err != nil {
		return 0, nil, errors.Trace(err)
	}
	if data == nil {
		// When no column is referenced, the data may be nil, like 'select count(*) from t'.
		// In this case, we need to create a zero length datum slice,
		// as caller will check if data is nil to finish iteration.
		data = make([]types.Datum, 0)
	}
	if !r.aggregate {
		handleBytes := row.GetHandle()
		datums, err := codec.Decode(handleBytes)
		if err != nil {
			return 0, nil, errors.Trace(err)
		}
		handle = datums[0].GetInt64()
	}
	r.cursor++
	return
}

// Close closes the sub result.
func (r *partialResult) Close() error {
	return nil
}

// Select do a select request, returns SelectResult.
// conncurrency: The max concurrency for underlying coprocessor request.
// keepOrder: If the result should returned in key order. For example if we need keep data in order by
//            scan index, we should set keepOrder to true.
func Select(client kv.Client, req *tipb.SelectRequest, concurrency int, keepOrder bool) (SelectResult, error) {
	// Convert tipb.*Request to kv.Request.
	kvReq, err := composeRequest(req, concurrency, keepOrder)
	if err != nil {
		return nil, errors.Trace(err)
	}
	resp := client.Send(kvReq)
	if resp == nil {
		return nil, errors.New("client returns nil response")
	}
	result := &selectResult{resp: resp}
	// If Aggregates is not nil, we should set result fields latter.
	if len(req.Aggregates) == 0 && len(req.GroupBy) == 0 {
		if req.TableInfo != nil {
			result.fields = ProtoColumnsToFieldTypes(req.TableInfo.Columns)
		} else {
			result.fields = ProtoColumnsToFieldTypes(req.IndexInfo.Columns)
			length := len(req.IndexInfo.Columns)
			if req.IndexInfo.Columns[length-1].GetPkHandle() {
				// Returned index row do not contains extra PKHandle column.
				result.fields = result.fields[:length-1]
			}
			result.index = true
		}
	} else {
		result.aggregate = true
	}
	return result, nil
}

// Convert tipb.Request to kv.Request.
func composeRequest(req *tipb.SelectRequest, concurrency int, keepOrder bool) (*kv.Request, error) {
	kvReq := &kv.Request{
		Concurrency: concurrency,
		KeepOrder:   keepOrder,
	}
	if req.IndexInfo != nil {
		kvReq.Tp = kv.ReqTypeIndex
		tid := req.IndexInfo.GetTableId()
		idxID := req.IndexInfo.GetIndexId()
		kvReq.KeyRanges = EncodeIndexRanges(tid, idxID, req.Ranges)
	} else {
		kvReq.Tp = kv.ReqTypeSelect
		tid := req.GetTableInfo().GetTableId()
		kvReq.KeyRanges = EncodeTableRanges(tid, req.Ranges)
	}
	if req.OrderBy != nil {
		kvReq.Desc = req.OrderBy[0].Desc
	}
	var err error
	kvReq.Data, err = proto.Marshal(req)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return kvReq, nil
}

// SupportExpression checks if the expression is supported by the client.
func SupportExpression(client kv.Client, expr *tipb.Expr) bool {
	return false
}

// XAPI error codes.
const (
	codeInvalidResp = 1
	codeNilResp     = 2
)

// FieldTypeFromPBColumn creates a types.FieldType from tipb.ColumnInfo.
func FieldTypeFromPBColumn(col *tipb.ColumnInfo) *types.FieldType {
	return &types.FieldType{
		Tp:      byte(col.GetTp()),
		Flen:    int(col.GetColumnLen()),
		Decimal: int(col.GetDecimal()),
		Elems:   col.Elems,
		Collate: mysql.Collations[uint8(col.GetCollation())],
	}
}

func columnToProto(c *model.ColumnInfo) *tipb.ColumnInfo {
	pc := &tipb.ColumnInfo{
		ColumnId:  c.ID,
		Collation: collationToProto(c.FieldType.Collate),
		ColumnLen: int32(c.FieldType.Flen),
		Decimal:   int32(c.FieldType.Decimal),
		Flag:      int32(c.Flag),
		Elems:     c.Elems,
	}
	pc.Tp = int32(c.FieldType.Tp)
	return pc
}

func collationToProto(c string) int32 {
	v, ok := mysql.CollationNames[c]
	if ok {
		return int32(v)
	}
	return int32(mysql.DefaultCollationID)
}

// ColumnsToProto converts a slice of model.ColumnInfo to a slice of tipb.ColumnInfo.
func ColumnsToProto(columns []*model.ColumnInfo, pkIsHandle bool) []*tipb.ColumnInfo {
	cols := make([]*tipb.ColumnInfo, 0, len(columns))
	for _, c := range columns {
		col := columnToProto(c)
		if pkIsHandle && mysql.HasPriKeyFlag(c.Flag) {
			col.PkHandle = true
		} else {
			col.PkHandle = false
		}
		cols = append(cols, col)
	}
	return cols
}

// ProtoColumnsToFieldTypes converts tipb column info slice to FieldTyps slice.
func ProtoColumnsToFieldTypes(pColumns []*tipb.ColumnInfo) []*types.FieldType {
	fields := make([]*types.FieldType, len(pColumns))
	for i, v := range pColumns {
		field := new(types.FieldType)
		field.Tp = byte(v.GetTp())
		field.Collate = mysql.Collations[byte(v.GetCollation())]
		field.Decimal = int(v.GetDecimal())
		field.Flen = int(v.GetColumnLen())
		field.Flag = uint(v.GetFlag())
		field.Elems = v.GetElems()
		fields[i] = field
	}
	return fields
}

// IndexToProto converts a model.IndexInfo to a tipb.IndexInfo.
func IndexToProto(t *model.TableInfo, idx *model.IndexInfo) *tipb.IndexInfo {
	pi := &tipb.IndexInfo{
		TableId: t.ID,
		IndexId: idx.ID,
		Unique:  idx.Unique,
	}
	cols := make([]*tipb.ColumnInfo, 0, len(idx.Columns)+1)
	for _, c := range idx.Columns {
		cols = append(cols, columnToProto(t.Columns[c.Offset]))
	}
	if t.PKIsHandle {
		// Coprocessor needs to know PKHandle column info, so we need to append it.
		for _, col := range t.Columns {
			if mysql.HasPriKeyFlag(col.Flag) {
				colPB := columnToProto(col)
				colPB.PkHandle = true
				cols = append(cols, colPB)
				break
			}
		}
	}
	pi.Columns = cols
	return pi
}

// EncodeTableRanges encodes table ranges into kv.KeyRanges.
func EncodeTableRanges(tid int64, rans []*tipb.KeyRange) []kv.KeyRange {
	keyRanges := make([]kv.KeyRange, 0, len(rans))
	for _, r := range rans {
		start := tablecodec.EncodeRowKey(tid, r.Low)
		end := tablecodec.EncodeRowKey(tid, r.High)
		nr := kv.KeyRange{
			StartKey: start,
			EndKey:   end,
		}
		keyRanges = append(keyRanges, nr)
	}
	return keyRanges
}

// EncodeIndexRanges encodes index ranges into kv.KeyRanges.
func EncodeIndexRanges(tid, idxID int64, rans []*tipb.KeyRange) []kv.KeyRange {
	keyRanges := make([]kv.KeyRange, 0, len(rans))
	for _, r := range rans {
		// Convert range to kv.KeyRange
		start := tablecodec.EncodeIndexSeekKey(tid, idxID, r.Low)
		end := tablecodec.EncodeIndexSeekKey(tid, idxID, r.High)
		nr := kv.KeyRange{
			StartKey: start,
			EndKey:   end,
		}
		keyRanges = append(keyRanges, nr)
	}
	return keyRanges
}
<commit_msg>*: Use gogo Marshal/Unmarshal (#1605)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package xapi

import (
	"io"
	"io/ioutil"

	"github.com/juju/errors"
	"github.com/pingcap/tidb/kv"
	"github.com/pingcap/tidb/model"
	"github.com/pingcap/tidb/mysql"
	"github.com/pingcap/tidb/tablecodec"
	"github.com/pingcap/tidb/terror"
	"github.com/pingcap/tidb/util/codec"
	"github.com/pingcap/tidb/util/types"
	"github.com/pingcap/tipb/go-tipb"
)

var (
	errInvalidResp = terror.ClassXEval.New(codeInvalidResp, "invalid response")
	errNilResp     = terror.ClassXEval.New(codeNilResp, "client returns nil response")
)

var (
	_ SelectResult  = &selectResult{}
	_ PartialResult = &partialResult{}
)

// SelectResult is an iterator of coprocessor partial results.
type SelectResult interface {
	// Next gets the next partial result.
	Next() (PartialResult, error)
	// SetFields sets the expected result type.
	SetFields(fields []*types.FieldType)
	// Close closes the iterator.
	Close() error
}

// PartialResult is the result from a single region server.
type PartialResult interface {
	// Next returns the next row of the sub result.
	// If no more row to return, data would be nil.
	Next() (handle int64, data []types.Datum, err error)
	// Close closes the partial result.
	Close() error
}

// SelectResult is used to get response rows from SelectRequest.
type selectResult struct {
	index     bool
	aggregate bool
	fields    []*types.FieldType
	resp      kv.Response
}

// Next returns the next row.
func (r *selectResult) Next() (pr PartialResult, err error) {
	var reader io.ReadCloser
	reader, err = r.resp.Next()
	if err != nil {
		return nil, errors.Trace(err)
	}
	if reader == nil {
		return nil, nil
	}
	pr = &partialResult{
		index:     r.index,
		fields:    r.fields,
		reader:    reader,
		aggregate: r.aggregate,
	}
	return
}

// SetFields sets select result field types.
func (r *selectResult) SetFields(fields []*types.FieldType) {
	r.fields = fields
}

// Close closes SelectResult.
func (r *selectResult) Close() error {
	return r.resp.Close()
}

// partialResult represents a subset of select result.
type partialResult struct {
	index     bool
	aggregate bool
	fields    []*types.FieldType
	reader    io.ReadCloser
	resp      *tipb.SelectResponse
	cursor    int
}

// Next returns the next row of the sub result.
// If no more row to return, data would be nil.
func (r *partialResult) Next() (handle int64, data []types.Datum, err error) {
	if r.resp == nil {
		r.resp = new(tipb.SelectResponse)
		var b []byte
		b, err = ioutil.ReadAll(r.reader)
		r.reader.Close()
		if err != nil {
			return 0, nil, errors.Trace(err)
		}
		err = r.resp.Unmarshal(b)
		if err != nil {
			return 0, nil, errors.Trace(err)
		}
		if r.resp.Error != nil {
			return 0, nil, errInvalidResp.Gen("[%d %s]", r.resp.Error.GetCode(), r.resp.Error.GetMsg())
		}
	}
	if r.cursor >= len(r.resp.Rows) {
		return 0, nil, nil
	}
	row := r.resp.Rows[r.cursor]
	data, err = tablecodec.DecodeValues(row.Data, r.fields, r.index)
	if err != nil {
		return 0, nil, errors.Trace(err)
	}
	if data == nil {
		// When no column is referenced, the data may be nil, like 'select count(*) from t'.
		// In this case, we need to create a zero length datum slice,
		// as caller will check if data is nil to finish iteration.
		data = make([]types.Datum, 0)
	}
	if !r.aggregate {
		handleBytes := row.GetHandle()
		datums, err := codec.Decode(handleBytes)
		if err != nil {
			return 0, nil, errors.Trace(err)
		}
		handle = datums[0].GetInt64()
	}
	r.cursor++
	return
}

// Close closes the sub result.
func (r *partialResult) Close() error {
	return nil
}

// Select do a select request, returns SelectResult.
// conncurrency: The max concurrency for underlying coprocessor request.
// keepOrder: If the result should returned in key order. For example if we need keep data in order by
//            scan index, we should set keepOrder to true.
func Select(client kv.Client, req *tipb.SelectRequest, concurrency int, keepOrder bool) (SelectResult, error) {
	// Convert tipb.*Request to kv.Request.
	kvReq, err := composeRequest(req, concurrency, keepOrder)
	if err != nil {
		return nil, errors.Trace(err)
	}
	resp := client.Send(kvReq)
	if resp == nil {
		return nil, errors.New("client returns nil response")
	}
	result := &selectResult{resp: resp}
	// If Aggregates is not nil, we should set result fields latter.
	if len(req.Aggregates) == 0 && len(req.GroupBy) == 0 {
		if req.TableInfo != nil {
			result.fields = ProtoColumnsToFieldTypes(req.TableInfo.Columns)
		} else {
			result.fields = ProtoColumnsToFieldTypes(req.IndexInfo.Columns)
			length := len(req.IndexInfo.Columns)
			if req.IndexInfo.Columns[length-1].GetPkHandle() {
				// Returned index row do not contains extra PKHandle column.
				result.fields = result.fields[:length-1]
			}
			result.index = true
		}
	} else {
		result.aggregate = true
	}
	return result, nil
}

// Convert tipb.Request to kv.Request.
func composeRequest(req *tipb.SelectRequest, concurrency int, keepOrder bool) (*kv.Request, error) {
	kvReq := &kv.Request{
		Concurrency: concurrency,
		KeepOrder:   keepOrder,
	}
	if req.IndexInfo != nil {
		kvReq.Tp = kv.ReqTypeIndex
		tid := req.IndexInfo.GetTableId()
		idxID := req.IndexInfo.GetIndexId()
		kvReq.KeyRanges = EncodeIndexRanges(tid, idxID, req.Ranges)
	} else {
		kvReq.Tp = kv.ReqTypeSelect
		tid := req.GetTableInfo().GetTableId()
		kvReq.KeyRanges = EncodeTableRanges(tid, req.Ranges)
	}
	if req.OrderBy != nil {
		kvReq.Desc = req.OrderBy[0].Desc
	}
	var err error
	kvReq.Data, err = req.Marshal()
	if err != nil {
		return nil, errors.Trace(err)
	}
	return kvReq, nil
}

// SupportExpression checks if the expression is supported by the client.
func SupportExpression(client kv.Client, expr *tipb.Expr) bool {
	return false
}

// XAPI error codes.
const (
	codeInvalidResp = 1
	codeNilResp     = 2
)

// FieldTypeFromPBColumn creates a types.FieldType from tipb.ColumnInfo.
func FieldTypeFromPBColumn(col *tipb.ColumnInfo) *types.FieldType {
	return &types.FieldType{
		Tp:      byte(col.GetTp()),
		Flen:    int(col.GetColumnLen()),
		Decimal: int(col.GetDecimal()),
		Elems:   col.Elems,
		Collate: mysql.Collations[uint8(col.GetCollation())],
	}
}

func columnToProto(c *model.ColumnInfo) *tipb.ColumnInfo {
	pc := &tipb.ColumnInfo{
		ColumnId:  c.ID,
		Collation: collationToProto(c.FieldType.Collate),
		ColumnLen: int32(c.FieldType.Flen),
		Decimal:   int32(c.FieldType.Decimal),
		Flag:      int32(c.Flag),
		Elems:     c.Elems,
	}
	pc.Tp = int32(c.FieldType.Tp)
	return pc
}

func collationToProto(c string) int32 {
	v, ok := mysql.CollationNames[c]
	if ok {
		return int32(v)
	}
	return int32(mysql.DefaultCollationID)
}

// ColumnsToProto converts a slice of model.ColumnInfo to a slice of tipb.ColumnInfo.
func ColumnsToProto(columns []*model.ColumnInfo, pkIsHandle bool) []*tipb.ColumnInfo {
	cols := make([]*tipb.ColumnInfo, 0, len(columns))
	for _, c := range columns {
		col := columnToProto(c)
		if pkIsHandle && mysql.HasPriKeyFlag(c.Flag) {
			col.PkHandle = true
		} else {
			col.PkHandle = false
		}
		cols = append(cols, col)
	}
	return cols
}

// ProtoColumnsToFieldTypes converts tipb column info slice to FieldTyps slice.
func ProtoColumnsToFieldTypes(pColumns []*tipb.ColumnInfo) []*types.FieldType {
	fields := make([]*types.FieldType, len(pColumns))
	for i, v := range pColumns {
		field := new(types.FieldType)
		field.Tp = byte(v.GetTp())
		field.Collate = mysql.Collations[byte(v.GetCollation())]
		field.Decimal = int(v.GetDecimal())
		field.Flen = int(v.GetColumnLen())
		field.Flag = uint(v.GetFlag())
		field.Elems = v.GetElems()
		fields[i] = field
	}
	return fields
}

// IndexToProto converts a model.IndexInfo to a tipb.IndexInfo.
func IndexToProto(t *model.TableInfo, idx *model.IndexInfo) *tipb.IndexInfo {
	pi := &tipb.IndexInfo{
		TableId: t.ID,
		IndexId: idx.ID,
		Unique:  idx.Unique,
	}
	cols := make([]*tipb.ColumnInfo, 0, len(idx.Columns)+1)
	for _, c := range idx.Columns {
		cols = append(cols, columnToProto(t.Columns[c.Offset]))
	}
	if t.PKIsHandle {
		// Coprocessor needs to know PKHandle column info, so we need to append it.
		for _, col := range t.Columns {
			if mysql.HasPriKeyFlag(col.Flag) {
				colPB := columnToProto(col)
				colPB.PkHandle = true
				cols = append(cols, colPB)
				break
			}
		}
	}
	pi.Columns = cols
	return pi
}

// EncodeTableRanges encodes table ranges into kv.KeyRanges.
func EncodeTableRanges(tid int64, rans []*tipb.KeyRange) []kv.KeyRange {
	keyRanges := make([]kv.KeyRange, 0, len(rans))
	for _, r := range rans {
		start := tablecodec.EncodeRowKey(tid, r.Low)
		end := tablecodec.EncodeRowKey(tid, r.High)
		nr := kv.KeyRange{
			StartKey: start,
			EndKey:   end,
		}
		keyRanges = append(keyRanges, nr)
	}
	return keyRanges
}

// EncodeIndexRanges encodes index ranges into kv.KeyRanges.
func EncodeIndexRanges(tid, idxID int64, rans []*tipb.KeyRange) []kv.KeyRange {
	keyRanges := make([]kv.KeyRange, 0, len(rans))
	for _, r := range rans {
		// Convert range to kv.KeyRange
		start := tablecodec.EncodeIndexSeekKey(tid, idxID, r.Low)
		end := tablecodec.EncodeIndexSeekKey(tid, idxID, r.High)
		nr := kv.KeyRange{
			StartKey: start,
			EndKey:   end,
		}
		keyRanges = append(keyRanges, nr)
	}
	return keyRanges
}
<|endoftext|>


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

package harnesses

import (
	"os/exec"
	"path/filepath"

	"golang.org/x/benchmarks/sweet/common"
	"golang.org/x/benchmarks/sweet/common/log"
)

const (
	server = "tile38-server"
)

type Tile38 struct{}

func (h Tile38) CheckPrerequisites() error {
	return nil
}

func (h Tile38) Get(srcDir string) error {
	return gitShallowClone(
		srcDir,
		"https://github.com/tidwall/tile38",
		"1.25.3",
	)
}

func (h Tile38) Build(cfg *common.Config, bcfg *common.BuildConfig) error {
	env := cfg.BuildEnv.Env

	// Add the Go tool to PATH, since tile38's Makefile doesn't provide enough
	// visibility into how tile38 is built to allow us to pass this information
	// directly.
	env = env.Prefix("PATH", filepath.Join(cfg.GoRoot, "bin")+":")

	cmd := exec.Command("make", "-C", bcfg.SrcDir)
	cmd.Env = env.Collapse()
	log.TraceCommand(cmd, false)
	if err := cmd.Run(); err != nil {
		return err
	}
	// Note that no matter what we do, the build script insists on putting the
	// binaries into the source directory, so copy the one we care about into
	// BinDir.
	if err := copyFile(filepath.Join(bcfg.BinDir, server), filepath.Join(bcfg.SrcDir, server)); err != nil {
		return err
	}
	return cfg.GoTool().BuildPath(bcfg.BenchDir, filepath.Join(bcfg.BinDir, "tile38-bench"))
}

func (h Tile38) Run(cfg *common.Config, rcfg *common.RunConfig) error {
	// Make sure all the data passed to the server is writable.
	// The server needs to be able to open its persistent storage as read-write.
	dataPath := filepath.Join(rcfg.AssetsDir, "data")
	if err := makeWriteable(dataPath); err != nil {
		return err
	}
	args := append(rcfg.Args, []string{
		"-host", "127.0.0.1",
		"-port", "9851",
		"-server", filepath.Join(rcfg.BinDir, server),
		"-data", dataPath,
		"-tmp", rcfg.TmpDir,
	}...)
	if rcfg.Short {
		args = append(args, "-short")
	}
	cmd := exec.Command(
		filepath.Join(rcfg.BinDir, "tile38-bench"),
		args...,
	)
	cmd.Env = cfg.ExecEnv.Collapse()
	cmd.Stdout = rcfg.Results
	cmd.Stderr = rcfg.Results
	log.TraceCommand(cmd, false)
	return cmd.Run()
}
<commit_msg>sweet/tile38: set GOROOT for the tile38 build<commit_after>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package harnesses

import (
	"os/exec"
	"path/filepath"

	"golang.org/x/benchmarks/sweet/common"
	"golang.org/x/benchmarks/sweet/common/log"
)

const (
	server = "tile38-server"
)

type Tile38 struct{}

func (h Tile38) CheckPrerequisites() error {
	return nil
}

func (h Tile38) Get(srcDir string) error {
	return gitShallowClone(
		srcDir,
		"https://github.com/tidwall/tile38",
		"1.25.3",
	)
}

func (h Tile38) Build(cfg *common.Config, bcfg *common.BuildConfig) error {
	env := cfg.BuildEnv.Env

	// Add the Go tool to PATH, since tile38's Makefile doesn't provide enough
	// visibility into how tile38 is built to allow us to pass this information
	// directly. Also set the GOROOT explicitly because it might have propagated
	// differently from the environment.
	env = env.Prefix("PATH", filepath.Join(cfg.GoRoot, "bin")+":")
	env = env.MustSet("GOROOT=" + cfg.GoRoot)

	cmd := exec.Command("make", "-C", bcfg.SrcDir)
	cmd.Env = env.Collapse()
	log.TraceCommand(cmd, false)
	if err := cmd.Run(); err != nil {
		return err
	}
	// Note that no matter what we do, the build script insists on putting the
	// binaries into the source directory, so copy the one we care about into
	// BinDir.
	if err := copyFile(filepath.Join(bcfg.BinDir, server), filepath.Join(bcfg.SrcDir, server)); err != nil {
		return err
	}
	return cfg.GoTool().BuildPath(bcfg.BenchDir, filepath.Join(bcfg.BinDir, "tile38-bench"))
}

func (h Tile38) Run(cfg *common.Config, rcfg *common.RunConfig) error {
	// Make sure all the data passed to the server is writable.
	// The server needs to be able to open its persistent storage as read-write.
	dataPath := filepath.Join(rcfg.AssetsDir, "data")
	if err := makeWriteable(dataPath); err != nil {
		return err
	}
	args := append(rcfg.Args, []string{
		"-host", "127.0.0.1",
		"-port", "9851",
		"-server", filepath.Join(rcfg.BinDir, server),
		"-data", dataPath,
		"-tmp", rcfg.TmpDir,
	}...)
	if rcfg.Short {
		args = append(args, "-short")
	}
	cmd := exec.Command(
		filepath.Join(rcfg.BinDir, "tile38-bench"),
		args...,
	)
	cmd.Env = cfg.ExecEnv.Collapse()
	cmd.Stdout = rcfg.Results
	cmd.Stderr = rcfg.Results
	log.TraceCommand(cmd, false)
	return cmd.Run()
}
<|endoftext|>


<commit_before>package tree
/*
#cgo LDFLAGS: -lxml2
#cgo CFLAGS: -I/usr/include/libxml2
#include <libxml/xmlversion.h>
#include <libxml/parser.h>
#include <libxml/HTMLparser.h>
#include <libxml/HTMLtree.h>
#include <libxml/xmlstring.h>
#include <libxml/xpath.h>

char *
DumpXmlToString(xmlDoc *doc) {
  xmlChar *buff;
  int buffersize;
  xmlDocDumpFormatMemory(doc,
                         &buff,
                         &buffersize, 1);
  return (char *)buff;
}

char *
DumpHtmlToString(xmlDoc *doc) {
  xmlChar *buff;
  int buffersize;
  htmlDocDumpMemory(doc, &buff, &buffersize);
  return (char *)buff;
}

xmlNode * GoXmlCastDocToNode(xmlDoc *doc) { return (xmlNode *)doc; }
*/
import "C"
import "unsafe"

type Doc struct {
	DocPtr *C.xmlDoc
	*XmlNode
}

func Parse(input string) *Doc {
	cInput := C.CString(input)
	doc := C.xmlParseMemory(cInput, C.int(len(input)))
	return NewNode(unsafe.Pointer(doc), nil).(*Doc)
}

// Returns the first element in the input string.
// Use Next() to access siblings
func (doc *Doc) ParseFragment(input string) Node {
	res := Parse("<root>" + input + "</root>").First().First()
	res.SetDoc(doc)
	return res
}

func NewDoc(ptr unsafe.Pointer) *Doc {
	doc := NewNode(ptr, nil).(*Doc)
	doc.DocPtr = (*C.xmlDoc)(ptr)
	return doc
}

func (doc *Doc) Free() {
	C.xmlFreeDoc(doc.DocPtr)
}

func (doc *Doc) MetaEncoding() string {
	return C.GoString((*C.char)(unsafe.Pointer(C.htmlGetMetaEncoding(doc.DocPtr))))
}

func (doc *Doc) String() string {
	// TODO: Decide what type of return to do HTML or XML
	return C.GoString(C.DumpXmlToString(doc.DocPtr))
}

func (doc *Doc) DumpHTML() string {
	return C.GoString(C.DumpHtmlToString(doc.DocPtr))
}

func (doc *Doc) DumpXML() string {
	return C.GoString(C.DumpXmlToString(doc.DocPtr))
}

func (doc *Doc) RootElement() *Element {
	return NewNode(unsafe.Pointer(C.xmlDocGetRootElement(doc.DocPtr)), doc).(*Element)
}
<commit_msg>free the doc object after FragementParse<commit_after>package tree
/*
#cgo LDFLAGS: -lxml2
#cgo CFLAGS: -I/usr/include/libxml2
#include <libxml/xmlversion.h>
#include <libxml/parser.h>
#include <libxml/HTMLparser.h>
#include <libxml/HTMLtree.h>
#include <libxml/xmlstring.h>
#include <libxml/xpath.h>

char *
DumpXmlToString(xmlDoc *doc) {
  xmlChar *buff;
  int buffersize;
  xmlDocDumpFormatMemory(doc,
                         &buff,
                         &buffersize, 1);
  return (char *)buff;
}

char *
DumpHtmlToString(xmlDoc *doc) {
  xmlChar *buff;
  int buffersize;
  htmlDocDumpMemory(doc, &buff, &buffersize);
  return (char *)buff;
}

xmlNode * GoXmlCastDocToNode(xmlDoc *doc) { return (xmlNode *)doc; }
*/
import "C"
import "unsafe"

type Doc struct {
	DocPtr *C.xmlDoc
	*XmlNode
}

func Parse(input string) *Doc {
	cInput := C.CString(input)
	doc := C.xmlParseMemory(cInput, C.int(len(input)))
	return NewNode(unsafe.Pointer(doc), nil).(*Doc)
}

// Returns the first element in the input string.
// Use Next() to access siblings
func (doc *Doc) ParseFragment(input string) Node {
	newDoc := Parse("<root>" + input + "</root>")
	defer newDoc.Free()
	res := newDoc.First().First()
	res.SetDoc(doc)
	return res
}

func NewDoc(ptr unsafe.Pointer) *Doc {
	doc := NewNode(ptr, nil).(*Doc)
	doc.DocPtr = (*C.xmlDoc)(ptr)
	return doc
}

func (doc *Doc) Free() {
	C.xmlFreeDoc(doc.DocPtr)
}

func (doc *Doc) MetaEncoding() string {
	return C.GoString((*C.char)(unsafe.Pointer(C.htmlGetMetaEncoding(doc.DocPtr))))
}

func (doc *Doc) String() string {
	// TODO: Decide what type of return to do HTML or XML
	return C.GoString(C.DumpXmlToString(doc.DocPtr))
}

func (doc *Doc) DumpHTML() string {
	return C.GoString(C.DumpHtmlToString(doc.DocPtr))
}

func (doc *Doc) DumpXML() string {
	return C.GoString(C.DumpXmlToString(doc.DocPtr))
}

func (doc *Doc) RootElement() *Element {
	return NewNode(unsafe.Pointer(C.xmlDocGetRootElement(doc.DocPtr)), doc).(*Element)
}
<|endoftext|>


<commit_before>package lightswarm

import (
	"bytes"
	"io/ioutil"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestFadeArgs(t *testing.T) {
	tt := []struct {
		name     string
		fade     Fade
		expected []byte
	}{
		{
			"fade to 255 at 1 step per 1 interval",
			Fade{255, 1, 1},
			[]byte{255, 1, 1},
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			bs := tc.fade.Args()
			assert.Equal(t, tc.expected, bs)
		})
	}
}

func TestFrameAddress(t *testing.T) {
	tt := []struct {
		name    string
		address uint16
		b1      byte
		b2      byte
	}{
		{
			"lowest address (1)",
			1,
			0,
			1,
		},
		{
			"real address (690)",
			690,
			2,
			178,
		},
		{
			"maximum address (65535)",
			65535,
			255,
			255,
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			f := Frame{Addr: tc.address}
			b1, b2 := f.address()
			assert.Equal(t, tc.b1, b1)
			assert.Equal(t, tc.b2, b2)
		})
	}
}

func TestFrameChecksum(t *testing.T) {
	tt := []struct {
		name     string
		bs       []byte
		expected byte
	}{
		{
			"simple bytes",
			[]byte{0, 1, 2, 3, 4},
			4,
		},
		{
			"real world bytes",
			[]byte{2, 178, ON},
			144,
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			f := Frame{}
			checksum := f.checksum(tc.bs)
			assert.Equal(t, tc.expected, checksum)
		})
	}
}

func TestFrameWrap(t *testing.T) {
	tt := []struct {
		name     string
		bs       []byte
		expected []byte
	}{
		{
			"no bytes",
			[]byte{},
			[]byte{END, END},
		},
		{
			"end byte in bytes",
			[]byte{END},
			[]byte{END, ESC, 0xDC, END},
		},
		{
			"esc byte in bytes",
			[]byte{ESC},
			[]byte{END, ESC, 0xDD, END},
		},
		{
			"turn 690 on",
			[]byte{2, 178, ON, 144},
			[]byte{END, 2, 178, ON, 144, END},
		},
		{
			"turn 738 on",
			[]byte{2, 226, ON, 192},
			[]byte{END, 2, 226, ON, ESC, 0xDC, END},
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			f := Frame{}
			frame := f.wrap(tc.bs)
			assert.Equal(t, tc.expected, frame)
		})
	}
}

func TestFrameBytes(t *testing.T) {
	tt := []struct {
		name     string
		frame    Frame
		expected []byte
	}{
		{
			"turn 690 on",
			Frame{690, ON, nil},
			[]byte{END, 2, 178, ON, 144, END},
		},
		{
			"fade 690 to 255 at 1 step per 1 interval",
			Frame{690, FADE_TO_LEVEL, []byte{255, 1, 1}},
			[]byte{END, 2, 178, FADE_TO_LEVEL, 255, 1, 1, 108, END},
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			bs := tc.frame.Bytes()
			assert.Equal(t, tc.expected, bs)
		})
	}
}

func TestLEDOn(t *testing.T) {
	tt := []struct {
		name     string
		addr     uint16
		buff     *bytes.Buffer
		expected []byte
		n        int
		err      error
	}{
		{
			"turn 690 on",
			690,
			bytes.NewBuffer(nil),
			[]byte{END, 2, 178, ON, 144, END},
			6,
			nil,
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			led := &LED{690, tc.buff}
			n, err := led.On()
			assert.Equal(t, tc.n, n)
			assert.Equal(t, tc.err, err)
			bs, err := ioutil.ReadAll(tc.buff)
			assert.Nil(t, err)
			assert.Equal(t, tc.expected, bs)
		})
	}
}
<commit_msg>Test for LED off<commit_after>package lightswarm

import (
	"bytes"
	"io/ioutil"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestFadeArgs(t *testing.T) {
	tt := []struct {
		name     string
		fade     Fade
		expected []byte
	}{
		{
			"fade to 255 at 1 step per 1 interval",
			Fade{255, 1, 1},
			[]byte{255, 1, 1},
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			bs := tc.fade.Args()
			assert.Equal(t, tc.expected, bs)
		})
	}
}

func TestFrameAddress(t *testing.T) {
	tt := []struct {
		name    string
		address uint16
		b1      byte
		b2      byte
	}{
		{
			"lowest address (1)",
			1,
			0,
			1,
		},
		{
			"real address (690)",
			690,
			2,
			178,
		},
		{
			"maximum address (65535)",
			65535,
			255,
			255,
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			f := Frame{Addr: tc.address}
			b1, b2 := f.address()
			assert.Equal(t, tc.b1, b1)
			assert.Equal(t, tc.b2, b2)
		})
	}
}

func TestFrameChecksum(t *testing.T) {
	tt := []struct {
		name     string
		bs       []byte
		expected byte
	}{
		{
			"simple bytes",
			[]byte{0, 1, 2, 3, 4},
			4,
		},
		{
			"real world bytes",
			[]byte{2, 178, ON},
			144,
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			f := Frame{}
			checksum := f.checksum(tc.bs)
			assert.Equal(t, tc.expected, checksum)
		})
	}
}

func TestFrameWrap(t *testing.T) {
	tt := []struct {
		name     string
		bs       []byte
		expected []byte
	}{
		{
			"no bytes",
			[]byte{},
			[]byte{END, END},
		},
		{
			"end byte in bytes",
			[]byte{END},
			[]byte{END, ESC, 0xDC, END},
		},
		{
			"esc byte in bytes",
			[]byte{ESC},
			[]byte{END, ESC, 0xDD, END},
		},
		{
			"turn 690 on",
			[]byte{2, 178, ON, 144},
			[]byte{END, 2, 178, ON, 144, END},
		},
		{
			"turn 738 on",
			[]byte{2, 226, ON, 192},
			[]byte{END, 2, 226, ON, ESC, 0xDC, END},
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			f := Frame{}
			frame := f.wrap(tc.bs)
			assert.Equal(t, tc.expected, frame)
		})
	}
}

func TestFrameBytes(t *testing.T) {
	tt := []struct {
		name     string
		frame    Frame
		expected []byte
	}{
		{
			"turn 690 on",
			Frame{690, ON, nil},
			[]byte{END, 2, 178, ON, 144, END},
		},
		{
			"fade 690 to 255 at 1 step per 1 interval",
			Frame{690, FADE_TO_LEVEL, []byte{255, 1, 1}},
			[]byte{END, 2, 178, FADE_TO_LEVEL, 255, 1, 1, 108, END},
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			bs := tc.frame.Bytes()
			assert.Equal(t, tc.expected, bs)
		})
	}
}

func TestLEDOn(t *testing.T) {
	tt := []struct {
		name     string
		addr     uint16
		buff     *bytes.Buffer
		expected []byte
		n        int
		err      error
	}{
		{
			"turn 690 on",
			690,
			bytes.NewBuffer(nil),
			[]byte{END, 2, 178, ON, 144, END},
			6,
			nil,
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			led := &LED{tc.addr, tc.buff}
			n, err := led.On()
			assert.Equal(t, tc.n, n)
			assert.Equal(t, tc.err, err)
			bs, err := ioutil.ReadAll(tc.buff)
			assert.Nil(t, err)
			assert.Equal(t, tc.expected, bs)
		})
	}
}

func TestLEDOff(t *testing.T) {
	tt := []struct {
		name     string
		addr     uint16
		buff     *bytes.Buffer
		expected []byte
		n        int
		err      error
	}{
		{
			"turn 690 off",
			690,
			bytes.NewBuffer(nil),
			[]byte{END, 2, 178, OFF, 145, END},
			6,
			nil,
		},
	}
	for _, tc := range tt {
		t.Run(tc.name, func(t *testing.T) {
			led := &LED{tc.addr, tc.buff}
			n, err := led.Off()
			assert.Equal(t, tc.n, n)
			assert.Equal(t, tc.err, err)
			bs, err := ioutil.ReadAll(tc.buff)
			assert.Nil(t, err)
			assert.Equal(t, tc.expected, bs)
		})
	}
}
<|endoftext|>


<commit_before>package zssh

import (
	"fmt"
	"github.com/yuin/gopher-lua"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

var ConfigFile string
var SSHConfigFile string
var Version = "0.3.0"

func Main() int {
	log.SetFlags(0)

	if len(os.Args) == 1 {
		fmt.Println(`zssh: extended ssh command.

version ` + Version + `

zssh custom options:
  --print	Print generated ssh config.
  --config	Edit config file.
  --hosts	List hosts.
  --macros	List macros.
  --update	Only update ssh config file. doesn't run ssh command.
  --zsh-completion	Output zsh completion code.
`)
		// show ssh help
		Run("ssh")
		return 0
	}

	var args []string
	if len(os.Args) >= 2 {
		// remove the command name
		args = os.Args[1:]
	}

	firstArg := args[0]

	printFlag := false
	updateFlag := false
	hostsFlag := false
	macrosFlag := false
	configFlag := false
	zshCompletinFlag := false

	for _, arg := range args {
		if arg == "--print" {
			printFlag = true
		}
		if arg == "--update" {
			updateFlag = true
		}
		if arg == "--hosts" {
			hostsFlag = true
		}
		if arg == "--macros" {
			macrosFlag = true
		}
		if arg == "--config" {
			configFlag = true
		}
		if arg == "--zsh-completion" {
			zshCompletinFlag = true
		}
	}

	if zshCompletinFlag {
		fmt.Print(ZSH_COMPLETION)
		return 0
	}

	if configFlag {
		Run("$EDITOR " + ConfigFile)
		return 0
	}

	lstate := lua.NewState()
	defer lstate.Close()

	LoadFunctions(lstate)

	if _, err := os.Stat(ConfigFile); err == nil {
		if err := lstate.DoFile(ConfigFile); err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	content, err := GenHostsConfig()
	if err != nil {
		log.Printf("Error: %s", err)
		return 1
	}

	if printFlag {
		fmt.Println(string(content))
		if !updateFlag {
			return 0
		}
	}

	if hostsFlag {
		for _, host := range Hosts {
			if !host.Hidden {
				if host.Description != "" {
					fmt.Printf("%s\t%s\n", host.Name, host.Description)
				} else {
					fmt.Printf("%s\n", host.Name)
				}
			}
		}

		return 0
	}

	if macrosFlag {
		for _, macro := range Macros {
			if macro.Description != "" {
				fmt.Printf("%s\t%s\n", macro.Name, macro.Description)
			} else {
				fmt.Printf("%s\n", macro.Name)
			}
		}

		return 0
	}

	// check modification.
	isModified := true
	if _, err := os.Stat(SSHConfigFile); err == nil {
		b, err := ioutil.ReadFile(SSHConfigFile)
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}

		if string(b) == string(content) {
			isModified = false
		}
	}

	// update .ssh/config
	if isModified {
		err = ioutil.WriteFile(SSHConfigFile, content, 0644)
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	if updateFlag {
		return 0
	}

	if macro, err := GetMacro(firstArg); err == nil {
		// there is a macro
		err := macro.Run()
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
		return 0
	}

	// setup ssh command
	cmdline := "ssh " + strings.Join(args, " ")

	// got hooks
	var hooks map[string]func() error
	if len(args) >= 1 {
		hostname := args[0]
		if host := GetHost(hostname); host != nil {
			hooks = host.Hooks
		}
	}

	// before hook
	if before := hooks["before"]; before != nil {
		err := before()
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	// run ssh
	err = Run(cmdline)

	// after hook
	if after := hooks["after"]; after != nil {
		err := after()
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	if err != nil {
		return 1
	}

	return 0
}

func userHomeDir() string {
	if runtime.GOOS == "windows" {
		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
		if home == "" {
			home = os.Getenv("USERPROFILE")
		}
		return home
	}
	return os.Getenv("HOME")
}

func init() {
	if ConfigFile == "" {
		home := userHomeDir()
		ConfigFile = filepath.Join(home, ".ssh/zssh.lua")
	}

	if SSHConfigFile == "" {
		home := userHomeDir()
		SSHConfigFile = filepath.Join(home, ".ssh/config")
	}

}

var ZSH_COMPLETION = `
_zssh_hosts() {
    local -a __zssh_hosts
    local -a __zssh_macros
    PRE_IFS=$IFS
    IFS=$'\n'
    __zssh_hosts=($(zssh --hosts | awk -F'\t' '{print $1":"$2}'))
    __zssh_macros=($(zssh --macros | awk -F'\t' '{print $1":"$2}'))
    IFS=$PRE_IFS
    _describe -t host "host" __zssh_hosts
    _describe -t macro "macro" __zssh_macros
}

_zssh () {
    local curcontext="$curcontext" state line
    typeset -A opt_args

    _arguments \
        '1: :->command'

    case $state in
        command)
            _zssh_hosts
            ;;
        *)
            _files
            ;;
    esac
}

compdef _zssh zssh

`
<commit_msg>update version<commit_after>package zssh

import (
	"fmt"
	"github.com/yuin/gopher-lua"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

var ConfigFile string
var SSHConfigFile string
var Version = "0.2.1"

func Main() int {
	log.SetFlags(0)

	if len(os.Args) == 1 {
		fmt.Println(`zssh: extended ssh command.

version ` + Version + `

zssh custom options:
  --print	Print generated ssh config.
  --config	Edit config file.
  --hosts	List hosts.
  --macros	List macros.
  --update	Only update ssh config file. doesn't run ssh command.
  --zsh-completion	Output zsh completion code.
`)
		// show ssh help
		Run("ssh")
		return 0
	}

	var args []string
	if len(os.Args) >= 2 {
		// remove the command name
		args = os.Args[1:]
	}

	firstArg := args[0]

	printFlag := false
	updateFlag := false
	hostsFlag := false
	macrosFlag := false
	configFlag := false
	zshCompletinFlag := false

	for _, arg := range args {
		if arg == "--print" {
			printFlag = true
		}
		if arg == "--update" {
			updateFlag = true
		}
		if arg == "--hosts" {
			hostsFlag = true
		}
		if arg == "--macros" {
			macrosFlag = true
		}
		if arg == "--config" {
			configFlag = true
		}
		if arg == "--zsh-completion" {
			zshCompletinFlag = true
		}
	}

	if zshCompletinFlag {
		fmt.Print(ZSH_COMPLETION)
		return 0
	}

	if configFlag {
		Run("$EDITOR " + ConfigFile)
		return 0
	}

	lstate := lua.NewState()
	defer lstate.Close()

	LoadFunctions(lstate)

	if _, err := os.Stat(ConfigFile); err == nil {
		if err := lstate.DoFile(ConfigFile); err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	content, err := GenHostsConfig()
	if err != nil {
		log.Printf("Error: %s", err)
		return 1
	}

	if printFlag {
		fmt.Println(string(content))
		if !updateFlag {
			return 0
		}
	}

	if hostsFlag {
		for _, host := range Hosts {
			if !host.Hidden {
				if host.Description != "" {
					fmt.Printf("%s\t%s\n", host.Name, host.Description)
				} else {
					fmt.Printf("%s\n", host.Name)
				}
			}
		}

		return 0
	}

	if macrosFlag {
		for _, macro := range Macros {
			if macro.Description != "" {
				fmt.Printf("%s\t%s\n", macro.Name, macro.Description)
			} else {
				fmt.Printf("%s\n", macro.Name)
			}
		}

		return 0
	}

	// check modification.
	isModified := true
	if _, err := os.Stat(SSHConfigFile); err == nil {
		b, err := ioutil.ReadFile(SSHConfigFile)
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}

		if string(b) == string(content) {
			isModified = false
		}
	}

	// update .ssh/config
	if isModified {
		err = ioutil.WriteFile(SSHConfigFile, content, 0644)
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	if updateFlag {
		return 0
	}

	if macro, err := GetMacro(firstArg); err == nil {
		// there is a macro
		err := macro.Run()
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
		return 0
	}

	// setup ssh command
	cmdline := "ssh " + strings.Join(args, " ")

	// got hooks
	var hooks map[string]func() error
	if len(args) >= 1 {
		hostname := args[0]
		if host := GetHost(hostname); host != nil {
			hooks = host.Hooks
		}
	}

	// before hook
	if before := hooks["before"]; before != nil {
		err := before()
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	// run ssh
	err = Run(cmdline)

	// after hook
	if after := hooks["after"]; after != nil {
		err := after()
		if err != nil {
			log.Printf("Error: %s", err)
			return 1
		}
	}

	if err != nil {
		return 1
	}

	return 0
}

func userHomeDir() string {
	if runtime.GOOS == "windows" {
		home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
		if home == "" {
			home = os.Getenv("USERPROFILE")
		}
		return home
	}
	return os.Getenv("HOME")
}

func init() {
	if ConfigFile == "" {
		home := userHomeDir()
		ConfigFile = filepath.Join(home, ".ssh/zssh.lua")
	}

	if SSHConfigFile == "" {
		home := userHomeDir()
		SSHConfigFile = filepath.Join(home, ".ssh/config")
	}

}

var ZSH_COMPLETION = `
_zssh_hosts() {
    local -a __zssh_hosts
    local -a __zssh_macros
    PRE_IFS=$IFS
    IFS=$'\n'
    __zssh_hosts=($(zssh --hosts | awk -F'\t' '{print $1":"$2}'))
    __zssh_macros=($(zssh --macros | awk -F'\t' '{print $1":"$2}'))
    IFS=$PRE_IFS
    _describe -t host "host" __zssh_hosts
    _describe -t macro "macro" __zssh_macros
}

_zssh () {
    local curcontext="$curcontext" state line
    typeset -A opt_args

    _arguments \
        '1: :->command'

    case $state in
        command)
            _zssh_hosts
            ;;
        *)
            _files
            ;;
    esac
}

compdef _zssh zssh

`
<|endoftext|>


<commit_before>package core

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"syscall"
)

type rssHandler struct {
	feed      Rss
	fs        http.Handler
	path      string
	imageBlob []byte
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
		handler.ServeHTTP(w, r)
	})
}
func isImagePath(path string, images []Image) bool {
	for i := 0; i < len(images); i++ {
		if strings.HasSuffix(images[i].Url, path) {
			return true
		}
	}
	return false
}

func (rss *rssHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path
	if path == "" || path == "/" {
		rss.feed.Out(w)
	} else if len(rss.imageBlob) > 0 && isImagePath(path, rss.feed.Channel.Images) {
		w.Write(rss.imageBlob)
	} else {
		http.StripPrefix(rss.path, rss.fs).ServeHTTP(w, r)
	}
}

func writeStartupMsg(workdir string, url string) {
	fmt.Printf(
		"\x1b[33;1m%v\x1b[0m \x1b[36;1m%v\x1b[0m \x1b[33;1mon:\x1b[0m \x1b[36;1m%v\x1b[0m\n",
		"Starting up dircast, serving", workdir, url)
	fmt.Println("Hit CTRL-C to stop the server")
}

func onShutdown(message string) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		fmt.Printf("\x1b[31;1m%v\x1b[0m\n", message)
		os.Exit(1)
	}()
}

func Server(source Source, logEnabled bool) error {

	url, _ := url.Parse(source.publicUrl)
	path := url.Path
	if !strings.HasSuffix(path, "/") {
		path += "/"
	}

	var imageBlob []byte
	if source.autoImage && len(source.image) > 0 {
		imageBlob = source.image
	}

	rss := &rssHandler{feed: *source.Rss(),
		fs: http.FileServer(http.Dir(source.Root)), imageBlob: imageBlob}

	http.Handle(path, rss)

	writeStartupMsg(source.Root, source.publicUrl)
	onShutdown("dircast stopped.")

	if logEnabled {
		http.ListenAndServe(url.Host, Log(http.DefaultServeMux))
	}
	return http.ListenAndServe(url.Host, nil)

}
<commit_msg>add new line<commit_after>package core

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"
	"os/signal"
	"strings"
	"syscall"
)

type rssHandler struct {
	feed      Rss
	fs        http.Handler
	path      string
	imageBlob []byte
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
		handler.ServeHTTP(w, r)
	})
}

func isImagePath(path string, images []Image) bool {
	for i := 0; i < len(images); i++ {
		if strings.HasSuffix(images[i].Url, path) {
			return true
		}
	}
	return false
}

func (rss *rssHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path
	if path == "" || path == "/" {
		rss.feed.Out(w)
	} else if len(rss.imageBlob) > 0 && isImagePath(path, rss.feed.Channel.Images) {
		w.Write(rss.imageBlob)
	} else {
		http.StripPrefix(rss.path, rss.fs).ServeHTTP(w, r)
	}
}

func writeStartupMsg(workdir string, url string) {
	fmt.Printf(
		"\x1b[33;1m%v\x1b[0m \x1b[36;1m%v\x1b[0m \x1b[33;1mon:\x1b[0m \x1b[36;1m%v\x1b[0m\n",
		"Starting up dircast, serving", workdir, url)
	fmt.Println("Hit CTRL-C to stop the server")
}

func onShutdown(message string) {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	signal.Notify(c, syscall.SIGTERM)
	go func() {
		<-c
		fmt.Printf("\x1b[31;1m%v\x1b[0m\n", message)
		os.Exit(1)
	}()
}

func Server(source Source, logEnabled bool) error {

	url, _ := url.Parse(source.publicUrl)
	path := url.Path
	if !strings.HasSuffix(path, "/") {
		path += "/"
	}

	var imageBlob []byte
	if source.autoImage && len(source.image) > 0 {
		imageBlob = source.image
	}

	rss := &rssHandler{feed: *source.Rss(),
		fs: http.FileServer(http.Dir(source.Root)), imageBlob: imageBlob}

	http.Handle(path, rss)

	writeStartupMsg(source.Root, source.publicUrl)
	onShutdown("dircast stopped.")

	if logEnabled {
		http.ListenAndServe(url.Host, Log(http.DefaultServeMux))
	}
	return http.ListenAndServe(url.Host, nil)

}
<|endoftext|>


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

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"syscall"

	"v.io/x/devtools/internal/collect"
	"v.io/x/devtools/internal/tool"
	"v.io/x/devtools/internal/util"
	"v.io/x/lib/cmdline"
)

var (
	gotoolsBinPathFlag string
	commentRE          = regexp.MustCompile("^($|[:space:]*#)")
)

func init() {
	cmdApi.Flags.StringVar(&gotoolsBinPathFlag, "gotools-bin", "", "The path to the gotools binary to use. If empty, gotools will be built if necessary.")
}

// cmdApi represents the "v23 api" command.
var cmdApi = &cmdline.Command{
	Name:  "api",
	Short: "Work with Vanadium's public API",
	Long: `
Use this command to ensure that no unintended changes are made to Vanadium's
public API.
`,
	Children: []*cmdline.Command{cmdApiCheck, cmdApiUpdate},
}

// cmdApiCheck represents the "v23 api check" command.
var cmdApiCheck = &cmdline.Command{
	Run:      runApiCheck,
	Name:     "check",
	Short:    "Check to see if any changes have been made to the public API.",
	Long:     "Check to see if any changes have been made to the public API.",
	ArgsName: "<projects>",
	ArgsLong: "<projects> is a list of Vanadium projects to check. If none are specified, all projects are checked.",
}

func readApiFileContents(path string, buf *bytes.Buffer) (e error) {
	file, err := os.Open(path)
	defer collect.Error(file.Close, &e)
	if err != nil {
		return err
	}
	reader := bufio.NewReader(file)
	for {
		line, err := reader.ReadBytes('\n')
		if !commentRE.Match(line) {
			buf.Write(line)
		}
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}
	}
	return
}

type packageChange struct {
	name        string
	projectName string
	apiFilePath string
	newApi      string

	// If true, indicates that there was a problem reading the old API file.
	apiFileError error
}

// buildGotools builds the gotools binary and returns the path to the built
// binary and the function to call to clean up the built binary (always
// non-nil). If the binary could not be built, the empty string and a non-nil
// error are returned.
//
// If the gotools_bin flag is specified, that path, a no-op cleanup and a
// nil error are returned.
func buildGotools(ctx *tool.Context) (string, func() error, error) {
	nopCleanup := func() error { return nil }
	if gotoolsBinPathFlag != "" {
		return gotoolsBinPathFlag, nopCleanup, nil
	}

	// Determine the location of the gotools source.
	projects, _, err := util.ReadManifest(ctx)
	if err != nil {
		return "", nopCleanup, err
	}

	project, ok := projects["third_party"]
	if !ok {
		return "", nopCleanup, fmt.Errorf(`project "third_party" not found`)
	}
	newGoPath := filepath.Join(project.Path, "go")

	// Build the gotools binary.
	tempDir, err := ctx.Run().TempDir("", "")
	if err != nil {
		return "", nopCleanup, err
	}
	cleanup := func() error { return ctx.Run().RemoveAll(tempDir) }

	gotoolsBin := filepath.Join(tempDir, "gotools")
	opts := ctx.Run().Opts()
	opts.Env["GOPATH"] = newGoPath
	if err := ctx.Run().CommandWithOpts(opts, "go", "build", "-o", gotoolsBin, "github.com/visualfc/gotools"); err != nil {
		return "", cleanup, err
	}

	return gotoolsBin, cleanup, nil
}

func isFailedApiCheckFatal(projectName string, apiCheckRequiredProjects map[string]bool, apiFileError error) bool {
	if pathError, ok := apiFileError.(*os.PathError); ok {
		if pathError.Err == os.ErrNotExist {
			if _, ok := apiCheckRequiredProjects[projectName]; !ok {
				return false
			}
		}
	}

	return true
}

func shouldIgnoreFile(file string) bool {
	if !strings.HasSuffix(file, ".go") {
		return true
	}
	pathComponents := strings.Split(file, string(os.PathSeparator))
	for _, component := range pathComponents {
		if component == "testdata" || component == "internal" {
			return true
		}
	}
	return false
}

func getPackageChanges(ctx *tool.Context, apiCheckRequiredProjects map[string]bool, args []string) (changes []packageChange, e error) {
	projects, _, err := util.ReadManifest(ctx)
	if err != nil {
		return nil, err
	}
	projectNames, err := parseArgs(args, projects)
	if err != nil {
		return nil, err
	}

	gotoolsBin, cleanup, err := buildGotools(ctx)
	if err != nil {
		return nil, err
	}
	defer collect.Error(cleanup, &e)

	for _, projectName := range projectNames {
		path := projects[projectName].Path
		branch, err := ctx.Git(tool.RootDirOpt(path)).CurrentBranchName()
		if err != nil {
			return nil, err
		}
		files, err := ctx.Git(tool.RootDirOpt(path)).ModifiedFiles("master", branch)
		if err != nil {
			return nil, err
		}
		// Extract the directories for these files.
		dirs := make(map[string]bool) // set
		for _, file := range files {
			if !shouldIgnoreFile(file) {
				dirs[filepath.Join(path, filepath.Dir(file))] = true
			}
		}
		if len(dirs) == 0 {
			continue
		}
		for dir := range dirs {
			// Read the existing public API file.
			apiFilePath := filepath.Join(dir, ".api")
			var apiFileContents bytes.Buffer
			apiFileError := readApiFileContents(apiFilePath, &apiFileContents)
			if apiFileError != nil {
				if !isFailedApiCheckFatal(projectName, apiCheckRequiredProjects, apiFileError) {
					// We couldn't read the API file, but
					// this project doesn't require one.
					// Just warn the user.
					fmt.Fprintf(ctx.Stderr(), "WARNING: could not read public API from %s: %v\n", apiFilePath, err)
					fmt.Fprintf(ctx.Stderr(), "WARNING: skipping public API check for %s\n", dir)
					continue
				}
			}
			var out bytes.Buffer
			opts := ctx.Run().Opts()
			opts.Stdout = &out
			if err := ctx.Run().CommandWithOpts(opts, gotoolsBin, "goapi", dir); err != nil {
				return nil, err
			}
			if apiFileError != nil || out.String() != apiFileContents.String() {
				// The user has changed the public API or we
				// couldn't read the public API in the first
				// place.
				changes = append(changes, packageChange{name: dir, projectName: projectName, apiFilePath: apiFilePath, newApi: out.String(), apiFileError: apiFileError})
			}
		}
	}
	return
}

func runApiCheck(command *cmdline.Command, args []string) error {
	return doApiCheck(command.Stdout(), command.Stderr(), args)
}

func doApiCheck(stdout, stderr io.Writer, args []string) error {
	ctx := tool.NewContext(tool.ContextOpts{
		Color:    &colorFlag,
		DryRun:   &dryRunFlag,
		Manifest: &manifestFlag,
		Verbose:  &verboseFlag,
		Stdout:   stdout,
		Stderr:   stderr,
	})
	config, err := util.LoadConfig(ctx)
	if err != nil {
		return err
	}
	changes, err := getPackageChanges(ctx, config.ApiCheckRequiredProjects(), args)
	if err != nil {
		return err
	} else if len(changes) > 0 {
		fmt.Fprintf(stdout, "Detected changes in the following %d package(s):\n", len(changes))
		for _, change := range changes {
			fmt.Fprintf(stdout, "For package %s\n", change.name)
			opts := ctx.Run().Opts()
			if change.apiFileError != nil {
				fmt.Fprintf(stdout, "ERROR: could not read the package's .api file: %v\n", change.apiFileError)
				fmt.Fprintf(stdout, "ERROR: a readable .api file is required for all packages in project %s\n", change.projectName)
				continue
			}
			opts.Stdin = strings.NewReader(change.newApi)
			opts.Stdout = stdout
			if err := ctx.Run().CommandWithOpts(opts, "diff", "-u", change.apiFilePath, "-"); err != nil {
				// We expect diff to return 1 if changes are
				// detected
				if exiterr, ok := err.(*exec.ExitError); ok {
					if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
						if status.ExitStatus() != 1 {
							continue
						}
					}
				}
				// If we got here, diff returned a non-nil err
				// other than an ExitError with status code=1
				fmt.Fprintf(ctx.Stderr(), "WARNING: got an error while running diff: %v", err)
			}
		}
	}
	return nil
}

// cmdApiUpdate represents the "v23 api fix" command.
var cmdApiUpdate = &cmdline.Command{
	Run:      runApiFix,
	Name:     "fix",
	Short:    "Updates the .api files to reflect your changes to the public API.",
	Long:     "Updates the .api files to reflect your changes to the public API.",
	ArgsName: "<projects>",
	ArgsLong: "<projects> is a list of Vanadium projects to update. If none are specified, all project APIs are updated.",
}

func runApiFix(command *cmdline.Command, args []string) error {
	ctx := tool.NewContextFromCommand(command, tool.ContextOpts{
		Color:    &colorFlag,
		DryRun:   &dryRunFlag,
		Manifest: &manifestFlag,
		Verbose:  &verboseFlag})
	config, err := util.LoadConfig(ctx)
	if err != nil {
		return err
	}
	changes, err := getPackageChanges(ctx, config.ApiCheckRequiredProjects(), args)
	if err != nil {
		return err
	}
	for _, change := range changes {
		if err := ctx.Run().WriteFile(change.apiFilePath, []byte(change.newApi), 0644); err != nil {
			return fmt.Errorf("WriteFile(%s) failed: %v", change.apiFilePath, err)
		}
		fmt.Fprintf(ctx.Stdout(), "Updated %s.\n", change.apiFilePath)
	}
	return nil
}
<commit_msg>v23: a couple of API check fixes<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"syscall"

	"v.io/x/devtools/internal/collect"
	"v.io/x/devtools/internal/tool"
	"v.io/x/devtools/internal/util"
	"v.io/x/lib/cmdline"
)

var (
	gotoolsBinPathFlag string
	commentRE          = regexp.MustCompile("^($|[:space:]*#)")
)

func init() {
	cmdApi.Flags.StringVar(&gotoolsBinPathFlag, "gotools-bin", "", "The path to the gotools binary to use. If empty, gotools will be built if necessary.")
}

// cmdApi represents the "v23 api" command.
var cmdApi = &cmdline.Command{
	Name:  "api",
	Short: "Work with Vanadium's public API",
	Long: `
Use this command to ensure that no unintended changes are made to Vanadium's
public API.
`,
	Children: []*cmdline.Command{cmdApiCheck, cmdApiUpdate},
}

// cmdApiCheck represents the "v23 api check" command.
var cmdApiCheck = &cmdline.Command{
	Run:      runApiCheck,
	Name:     "check",
	Short:    "Check to see if any changes have been made to the public API.",
	Long:     "Check to see if any changes have been made to the public API.",
	ArgsName: "<projects>",
	ArgsLong: "<projects> is a list of Vanadium projects to check. If none are specified, all projects are checked.",
}

func readApiFileContents(path string, buf *bytes.Buffer) (e error) {
	file, err := os.Open(path)
	defer collect.Error(file.Close, &e)
	if err != nil {
		return err
	}
	reader := bufio.NewReader(file)
	for {
		line, err := reader.ReadBytes('\n')
		if !commentRE.Match(line) {
			buf.Write(line)
		}
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}
	}
	return
}

type packageChange struct {
	name        string
	projectName string
	apiFilePath string
	newApi      string

	// If true, indicates that there was a problem reading the old API file.
	apiFileError error
}

// buildGotools builds the gotools binary and returns the path to the built
// binary and the function to call to clean up the built binary (always
// non-nil). If the binary could not be built, the empty string and a non-nil
// error are returned.
//
// If the gotools_bin flag is specified, that path, a no-op cleanup and a
// nil error are returned.
func buildGotools(ctx *tool.Context) (string, func() error, error) {
	nopCleanup := func() error { return nil }
	if gotoolsBinPathFlag != "" {
		return gotoolsBinPathFlag, nopCleanup, nil
	}

	// Determine the location of the gotools source.
	projects, _, err := util.ReadManifest(ctx)
	if err != nil {
		return "", nopCleanup, err
	}

	project, ok := projects["third_party"]
	if !ok {
		return "", nopCleanup, fmt.Errorf(`project "third_party" not found`)
	}
	newGoPath := filepath.Join(project.Path, "go")

	// Build the gotools binary.
	tempDir, err := ctx.Run().TempDir("", "")
	if err != nil {
		return "", nopCleanup, err
	}
	cleanup := func() error { return ctx.Run().RemoveAll(tempDir) }

	gotoolsBin := filepath.Join(tempDir, "gotools")
	opts := ctx.Run().Opts()
	opts.Env["GOPATH"] = newGoPath
	if err := ctx.Run().CommandWithOpts(opts, "go", "build", "-o", gotoolsBin, "github.com/visualfc/gotools"); err != nil {
		return "", cleanup, err
	}

	return gotoolsBin, cleanup, nil
}

func isFailedApiCheckFatal(projectName string, apiCheckRequiredProjects map[string]bool, apiFileError error) bool {
	if pathError, ok := apiFileError.(*os.PathError); ok {
		if pathError.Err == os.ErrNotExist {
			if _, ok := apiCheckRequiredProjects[projectName]; !ok {
				return false
			}
		}
	}

	return true
}

func shouldIgnoreFile(file string) bool {
	if !strings.HasSuffix(file, ".go") {
		return true
	}
	pathComponents := strings.Split(file, string(os.PathSeparator))
	for _, component := range pathComponents {
		if component == "testdata" || component == "internal" {
			return true
		}
	}
	return false
}

func getPackageChanges(ctx *tool.Context, apiCheckRequiredProjects map[string]bool, args []string) (changes []packageChange, e error) {
	projects, _, err := util.ReadManifest(ctx)
	if err != nil {
		return nil, err
	}
	projectNames, err := parseArgs(args, projects)
	if err != nil {
		return nil, err
	}

	gotoolsBin, cleanup, err := buildGotools(ctx)
	if err != nil {
		return nil, err
	}
	defer collect.Error(cleanup, &e)

	for _, projectName := range projectNames {
		path := projects[projectName].Path
		branch, err := ctx.Git(tool.RootDirOpt(path)).CurrentBranchName()
		if err != nil {
			return nil, err
		}
		files, err := ctx.Git(tool.RootDirOpt(path)).ModifiedFiles("master", branch)
		if err != nil {
			return nil, err
		}
		// Extract the directories for these files.
		dirs := make(map[string]bool) // set
		for _, file := range files {
			if !shouldIgnoreFile(file) {
				dirs[filepath.Join(path, filepath.Dir(file))] = true
			}
		}
		if len(dirs) == 0 {
			continue
		}
		for dir := range dirs {
			// Read the existing public API file.
			apiFilePath := filepath.Join(dir, ".api")
			var apiFileContents bytes.Buffer
			apiFileError := readApiFileContents(apiFilePath, &apiFileContents)
			if apiFileError != nil {
				if !isFailedApiCheckFatal(projectName, apiCheckRequiredProjects, apiFileError) {
					// We couldn't read the API file, but
					// this project doesn't require one.
					// Just warn the user.
					fmt.Fprintf(ctx.Stderr(), "WARNING: could not read public API from %s: %v\n", apiFilePath, err)
					fmt.Fprintf(ctx.Stderr(), "WARNING: skipping public API check for %s\n", dir)
					continue
				}
			}
			var out bytes.Buffer
			opts := ctx.Run().Opts()
			opts.Stdout = &out
			if err := ctx.Run().CommandWithOpts(opts, "v23", "run", gotoolsBin, "goapi", dir); err != nil {
				return nil, err
			}
			if apiFileError != nil || out.String() != apiFileContents.String() {
				// The user has changed the public API or we
				// couldn't read the public API in the first
				// place.
				changes = append(changes, packageChange{name: dir, projectName: projectName, apiFilePath: apiFilePath, newApi: out.String(), apiFileError: apiFileError})
			}
		}
	}
	return
}

func runApiCheck(command *cmdline.Command, args []string) error {
	return doApiCheck(command.Stdout(), command.Stderr(), args)
}

func doApiCheck(stdout, stderr io.Writer, args []string) error {
	ctx := tool.NewContext(tool.ContextOpts{
		Color:    &colorFlag,
		DryRun:   &dryRunFlag,
		Manifest: &manifestFlag,
		Verbose:  &verboseFlag,
		Stdout:   stdout,
		Stderr:   stderr,
	})
	config, err := util.LoadConfig(ctx)
	if err != nil {
		return err
	}
	changes, err := getPackageChanges(ctx, config.ApiCheckRequiredProjects(), args)
	if err != nil {
		return err
	} else if len(changes) > 0 {
		fmt.Fprintf(stdout, "Detected changes in the following %d package(s):\n", len(changes))
		for _, change := range changes {
			fmt.Fprintf(stdout, "For package %s\n", change.name)
			opts := ctx.Run().Opts()
			if change.apiFileError != nil {
				fmt.Fprintf(stdout, "ERROR: could not read the package's .api file: %v\n", change.apiFileError)
				fmt.Fprintf(stdout, "ERROR: a readable .api file is required for all packages in project %s\n", change.projectName)
				continue
			}
			opts.Stdin = strings.NewReader(change.newApi)
			opts.Stdout = stdout
			if err := ctx.Run().CommandWithOpts(opts, "diff", "-u", change.apiFilePath, "-"); err != nil {
				// We expect diff to return 1 if changes are
				// detected
				if exiterr, ok := err.(*exec.ExitError); ok {
					if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
						if status.ExitStatus() == 1 {
							continue
						}
					}
				}
				// If we got here, diff returned a non-nil err
				// other than an ExitError with status code=1
				fmt.Fprintf(ctx.Stderr(), "WARNING: got an error while running diff: %v\n", err)
			}
		}
	}
	return nil
}

// cmdApiUpdate represents the "v23 api fix" command.
var cmdApiUpdate = &cmdline.Command{
	Run:      runApiFix,
	Name:     "fix",
	Short:    "Updates the .api files to reflect your changes to the public API.",
	Long:     "Updates the .api files to reflect your changes to the public API.",
	ArgsName: "<projects>",
	ArgsLong: "<projects> is a list of Vanadium projects to update. If none are specified, all project APIs are updated.",
}

func runApiFix(command *cmdline.Command, args []string) error {
	ctx := tool.NewContextFromCommand(command, tool.ContextOpts{
		Color:    &colorFlag,
		DryRun:   &dryRunFlag,
		Manifest: &manifestFlag,
		Verbose:  &verboseFlag})
	config, err := util.LoadConfig(ctx)
	if err != nil {
		return err
	}
	changes, err := getPackageChanges(ctx, config.ApiCheckRequiredProjects(), args)
	if err != nil {
		return err
	}
	for _, change := range changes {
		if err := ctx.Run().WriteFile(change.apiFilePath, []byte(change.newApi), 0644); err != nil {
			return fmt.Errorf("WriteFile(%s) failed: %v", change.apiFilePath, err)
		}
		fmt.Fprintf(ctx.Stdout(), "Updated %s.\n", change.apiFilePath)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gbinary_test

import (
	"github.com/gogf/gf/g/encoding/gbinary"
	"github.com/gogf/gf/g/test/gtest"
	"math"
	"testing"
)

var testData = map[string]interface{}{
	"nil":         nil,
	"int":         int(123),
	"int8":        int8(-99),
	"int8.max":    math.MaxInt8,
	"int16":       int16(123),
	"int16.max":   math.MaxInt16,
	"int32":       int32(-199),
	"int32.max":   math.MaxInt32,
	"int64":       int64(123),
	"int64.max":   math.MaxInt64,
	"uint":        uint(123),
	"uint8":       uint8(123),
	"uint8.max":   math.MaxUint8,
	"uint16":      uint16(9999),
	"uint16.max":  math.MaxUint16,
	"uint32":      uint32(123),
	"uint32.max":  math.MaxUint32,
	"uint64":      uint64(123),
	"uint64.max":  math.MaxUint32 + 1,
	"bool.true":   true,
	"bool.false":  false,
	"string":      "hehe haha",
	"byte":        []byte("hehe haha"),
	"float32":     float32(123.456),
	"float32.max": math.MaxFloat32,
	"float64":     float64(123.456),
	"float64.max": math.MaxFloat64,
}

func TestEncodeAndDecode(t *testing.T) {
	for k, v := range testData {
		ve := gbinary.Encode(v)
		ve1 := gbinary.EncodeByLength(len(ve), v)

		//t.Logf("%s:%v, encoded:%v\n", k, v, ve)
		switch v.(type) {
		case int:
			gtest.Assert(gbinary.DecodeToInt(ve), v)
			gtest.Assert(gbinary.DecodeToInt(ve1), v)
		case int8:
			gtest.Assert(gbinary.DecodeToInt8(ve), v)
			gtest.Assert(gbinary.DecodeToInt8(ve1), v)
		case int16:
			gtest.Assert(gbinary.DecodeToInt16(ve), v)
			gtest.Assert(gbinary.DecodeToInt16(ve1), v)
		case int32:
			gtest.Assert(gbinary.DecodeToInt32(ve), v)
			gtest.Assert(gbinary.DecodeToInt32(ve1), v)
		case int64:
			gtest.Assert(gbinary.DecodeToInt64(ve), v)
			gtest.Assert(gbinary.DecodeToInt64(ve1), v)
		case uint:
			gtest.Assert(gbinary.DecodeToUint(ve), v)
			gtest.Assert(gbinary.DecodeToUint(ve1), v)
		case uint8:
			gtest.Assert(gbinary.DecodeToUint8(ve), v)
			gtest.Assert(gbinary.DecodeToUint8(ve1), v)
		case uint16:
			gtest.Assert(gbinary.DecodeToUint16(ve1), v)
			gtest.Assert(gbinary.DecodeToUint16(ve), v)
		case uint32:
			gtest.Assert(gbinary.DecodeToUint32(ve1), v)
			gtest.Assert(gbinary.DecodeToUint32(ve), v)
		case uint64:
			gtest.Assert(gbinary.DecodeToUint64(ve), v)
			gtest.Assert(gbinary.DecodeToUint64(ve1), v)
		case bool:
			gtest.Assert(gbinary.DecodeToBool(ve), v)
			gtest.Assert(gbinary.DecodeToBool(ve1), v)
		case string:
			gtest.Assert(gbinary.DecodeToString(ve), v)
			gtest.Assert(gbinary.DecodeToString(ve1), v)
		case float32:
			gtest.Assert(gbinary.DecodeToFloat32(ve), v)
			gtest.Assert(gbinary.DecodeToFloat32(ve1), v)
		case float64:
			gtest.Assert(gbinary.DecodeToFloat64(ve), v)
			gtest.Assert(gbinary.DecodeToFloat64(ve1), v)
		default:
			if v == nil {
				continue
			}
			res := make([]byte, len(ve))
			err := gbinary.Decode(ve, res)
			if err != nil {
				t.Errorf("test data: %s, %v, error:%v", k, v, err)
			}
			gtest.Assert(res, v)
		}
	}
}

type User struct {
	Name string
	Age  int
	Url  string
}

func TestEncodeStruct(t *testing.T) {
	user := User{"wenzi1", 999, "www.baidu.com"}
	ve := gbinary.Encode(user)
	s := gbinary.DecodeToString(ve)
	gtest.Assert(string(s), s)
}

var testBitData = []int{0, 99, 122, 129, 222, 999, 22322}

func TestBits(t *testing.T) {
	for i := range testBitData {
		bits := make([]gbinary.Bit, 0)
		res := gbinary.EncodeBits(bits, testBitData[i], 64)

		gtest.Assert(gbinary.DecodeBits(res), testBitData[i])
		gtest.Assert(gbinary.DecodeBitsToUint(res), uint(testBitData[i]))

		gtest.Assert(gbinary.DecodeBytesToBits(gbinary.EncodeBitsToBytes(res)), res)
	}

}
<commit_msg>add unit test<commit_after>// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package gbinary_test

import (
	"github.com/gogf/gf/g/encoding/gbinary"
	"github.com/gogf/gf/g/test/gtest"
	"math"
	"testing"
)

var testData = map[string]interface{}{
	//"nil":         nil,
	"int":         int(123),
	"int8":        int8(-99),
	"int8.max":    math.MaxInt8,
	"int16":       int16(123),
	"int16.max":   math.MaxInt16,
	"int32":       int32(-199),
	"int32.max":   math.MaxInt32,
	"int64":       int64(123),
	"int64.max":   math.MaxInt64,
	"uint":        uint(123),
	"uint8":       uint8(123),
	"uint8.max":   math.MaxUint8,
	"uint16":      uint16(9999),
	"uint16.max":  math.MaxUint16,
	"uint32":      uint32(123),
	"uint32.max":  math.MaxUint32,
	"uint64":      uint64(123),
	"uint64.max":  math.MaxUint32 + 1,
	"bool.true":   true,
	"bool.false":  false,
	"string":      "hehe haha",
	"byte":        []byte("hehe haha"),
	"float32":     float32(123.456),
	"float32.max": math.MaxFloat32,
	"float64":     float64(123.456),
	"float64.max": math.MaxFloat64,
}

func TestEncodeAndDecode(t *testing.T) {
	for k, v := range testData {
		ve := gbinary.Encode(v)
		ve1 := gbinary.EncodeByLength(len(ve), v)

		//t.Logf("%s:%v, encoded:%v\n", k, v, ve)
		switch v.(type) {
		case int:
			gtest.Assert(gbinary.DecodeToInt(ve), v)
			gtest.Assert(gbinary.DecodeToInt(ve1), v)
		case int8:
			gtest.Assert(gbinary.DecodeToInt8(ve), v)
			gtest.Assert(gbinary.DecodeToInt8(ve1), v)
		case int16:
			gtest.Assert(gbinary.DecodeToInt16(ve), v)
			gtest.Assert(gbinary.DecodeToInt16(ve1), v)
		case int32:
			gtest.Assert(gbinary.DecodeToInt32(ve), v)
			gtest.Assert(gbinary.DecodeToInt32(ve1), v)
		case int64:
			gtest.Assert(gbinary.DecodeToInt64(ve), v)
			gtest.Assert(gbinary.DecodeToInt64(ve1), v)
		case uint:
			gtest.Assert(gbinary.DecodeToUint(ve), v)
			gtest.Assert(gbinary.DecodeToUint(ve1), v)
		case uint8:
			gtest.Assert(gbinary.DecodeToUint8(ve), v)
			gtest.Assert(gbinary.DecodeToUint8(ve1), v)
		case uint16:
			gtest.Assert(gbinary.DecodeToUint16(ve1), v)
			gtest.Assert(gbinary.DecodeToUint16(ve), v)
		case uint32:
			gtest.Assert(gbinary.DecodeToUint32(ve1), v)
			gtest.Assert(gbinary.DecodeToUint32(ve), v)
		case uint64:
			gtest.Assert(gbinary.DecodeToUint64(ve), v)
			gtest.Assert(gbinary.DecodeToUint64(ve1), v)
		case bool:
			gtest.Assert(gbinary.DecodeToBool(ve), v)
			gtest.Assert(gbinary.DecodeToBool(ve1), v)
		case string:
			gtest.Assert(gbinary.DecodeToString(ve), v)
			gtest.Assert(gbinary.DecodeToString(ve1), v)
		case float32:
			gtest.Assert(gbinary.DecodeToFloat32(ve), v)
			gtest.Assert(gbinary.DecodeToFloat32(ve1), v)
		case float64:
			gtest.Assert(gbinary.DecodeToFloat64(ve), v)
			gtest.Assert(gbinary.DecodeToFloat64(ve1), v)
		default:
			if v == nil {
				continue
			}
			res := make([]byte, len(ve))
			err := gbinary.Decode(ve, res)
			if err != nil {
				t.Errorf("test data: %s, %v, error:%v", k, v, err)
			}
			gtest.Assert(res, v)
		}
	}
}

type User struct {
	Name string
	Age  int
	Url  string
}

func TestEncodeStruct(t *testing.T) {
	user := User{"wenzi1", 999, "www.baidu.com"}
	ve := gbinary.Encode(user)
	s := gbinary.DecodeToString(ve)
	gtest.Assert(string(s), s)
}

var testBitData = []int{0, 99, 122, 129, 222, 999, 22322}

func TestBits(t *testing.T) {
	for i := range testBitData {
		bits := make([]gbinary.Bit, 0)
		res := gbinary.EncodeBits(bits, testBitData[i], 64)

		gtest.Assert(gbinary.DecodeBits(res), testBitData[i])
		gtest.Assert(gbinary.DecodeBitsToUint(res), uint(testBitData[i]))

		gtest.Assert(gbinary.DecodeBytesToBits(gbinary.EncodeBitsToBytes(res)), res)
	}

}
<|endoftext|>