<commit_before>// Copyright 2018 Google LLC
//
// 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package util

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
)

// CompileProtos regenerates all of the generated source code for the Showcase
// API including the generated messages, gRPC services, go gapic clients,
// and the generated CLI. This must be ran from the root directory
// of the gapic-showcase repository.
func CompileProtos(version string) {
	// Check if protoc is installed.
	if err := exec.Command("protoc", "--version").Run(); err != nil {
		log.Fatal("Error: 'protoc' is expected to be installed on the path.")
	}

	// Setup paths
	pwd, err := os.Getwd()
	if err != nil {
		log.Fatalf("Error: unable to get working dir: %+v", err)
	}

	outDir, err := ioutil.TempDir(os.TempDir(), "gapic-showcase")
	if err != nil {
		log.Fatalf("Error: unable to create a temporary dir: %+v\n", err)
	}
	defer os.RemoveAll(outDir)

	protos := filepath.Join("schema", "google", "showcase", version, "*.proto")
	files, err := filepath.Glob(protos)
	if err != nil {
		log.Fatal("Error: failed to find protos in " + protos)
	}

	// Run protoc
	command := []string{
		"protoc",
		"--experimental_allow_proto3_optional",
		"--proto_path=schema/api-common-protos",
		"--proto_path=schema",
		// Disable go_cli generation until the generator supports it.
		//
		// TODO(ndietz): reenable once issue is resolved:
		// https://github.com/googleapis/gapic-generator-go/issues/378
		// "--go_cli_out=" + filepath.Join("cmd", "gapic-showcase"),
		// "--go_cli_opt=root=gapic-showcase",
		// "--go_cli_opt=gapic=github.com/googleapis/gapic-showcase/client",
		// "--go_cli_opt=fmt=false",
		"--go_gapic_out=" + outDir,
		"--go_gapic_opt=go-gapic-package=github.com/googleapis/gapic-showcase/client;client",
		"--go_gapic_opt=grpc-service-config=schema/google/showcase/v1beta1/showcase_grpc_service_config.json",
		"--go_out=plugins=grpc:" + outDir,
	}
	Execute(append(command, files...)...)

	// Copy generated code back into repo.
	tempClient := filepath.Join(outDir, "github.com", "googleapis", "gapic-showcase", "client")
	tempServer := filepath.Join(outDir, "github.com", "googleapis", "gapic-showcase", "server")
	command = []string{
		"cp",
		"-r",
		tempClient,
		tempServer,
		pwd,
	}
	Execute(command...)

	// Fix some generated errors.
	fixes := []struct {
		file string
		fix  string
	}{
		{
			"cmd/gapic-showcase/verify-test.go",
			"/ByteSliceVar/d",
		},
		{
			"cmd/gapic-showcase/wait.go",
			"s/EndEnd_time/EndEndTime/g",
		},
	}
	command = []string{
		"sed",
		"-i.bak",
	}
	for _, f := range fixes {
		Execute(append(command, f.fix, f.file)...)

		// Remove the backup file.
		Execute("rm", fmt.Sprintf("%s.bak", f.file))
	}

	// Format generated output
	Execute("go", "fmt", "./...")
}
<commit_msg>chore: reenable go_cli generation (#367)<commit_after>// Copyright 2018 Google LLC
//
// 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
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package util

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
)

// CompileProtos regenerates all of the generated source code for the Showcase
// API including the generated messages, gRPC services, go gapic clients,
// and the generated CLI. This must be ran from the root directory
// of the gapic-showcase repository.
func CompileProtos(version string) {
	// Check if protoc is installed.
	if err := exec.Command("protoc", "--version").Run(); err != nil {
		log.Fatal("Error: 'protoc' is expected to be installed on the path.")
	}

	// Setup paths
	pwd, err := os.Getwd()
	if err != nil {
		log.Fatalf("Error: unable to get working dir: %+v", err)
	}

	outDir, err := ioutil.TempDir(os.TempDir(), "gapic-showcase")
	if err != nil {
		log.Fatalf("Error: unable to create a temporary dir: %+v\n", err)
	}
	defer os.RemoveAll(outDir)

	protos := filepath.Join("schema", "google", "showcase", version, "*.proto")
	files, err := filepath.Glob(protos)
	if err != nil {
		log.Fatal("Error: failed to find protos in " + protos)
	}

	// Run protoc
	command := []string{
		"protoc",
		"--experimental_allow_proto3_optional",
		"--proto_path=schema/api-common-protos",
		"--proto_path=schema",
		"--go_cli_out=" + filepath.Join("cmd", "gapic-showcase"),
		"--go_cli_opt=root=gapic-showcase",
		"--go_cli_opt=gapic=github.com/googleapis/gapic-showcase/client",
		"--go_cli_opt=fmt=false",
		"--go_gapic_out=" + outDir,
		"--go_gapic_opt=go-gapic-package=github.com/googleapis/gapic-showcase/client;client",
		"--go_gapic_opt=grpc-service-config=schema/google/showcase/v1beta1/showcase_grpc_service_config.json",
		"--go_out=plugins=grpc:" + outDir,
	}
	Execute(append(command, files...)...)

	// Copy generated code back into repo.
	tempClient := filepath.Join(outDir, "github.com", "googleapis", "gapic-showcase", "client")
	tempServer := filepath.Join(outDir, "github.com", "googleapis", "gapic-showcase", "server")
	command = []string{
		"cp",
		"-r",
		tempClient,
		tempServer,
		pwd,
	}
	Execute(command...)

	// Fix some generated errors.
	fixes := []struct {
		file string
		fix  string
	}{
		{
			"cmd/gapic-showcase/verify-test.go",
			"/ByteSliceVar/d",
		},
		{
			"cmd/gapic-showcase/wait.go",
			"s/EndEnd_time/EndEndTime/g",
		},
	}
	command = []string{
		"sed",
		"-i.bak",
	}
	for _, f := range fixes {
		Execute(append(command, f.fix, f.file)...)

		// Remove the backup file.
		Execute("rm", fmt.Sprintf("%s.bak", f.file))
	}

	// Format generated output
	Execute("go", "fmt", "./...")
}
<|endoftext|>


<commit_before>package ssdb

const (
	SALVESTATUS_DISCONNECTED = 0
	SALVESTATUS_INIT = 1
	SALVESTATUS_COPY = 2
	SALVESTATUS_SYNC = 4
	SALVESTATUS_OUT_OF_SYNC = 8

	DATATYPE_SYNCLOG    = 1
	DATATYPE_KV         = 'k'
	DATATYPE_HASH       = 'h'
	DATATYPE_HSIZE      = 'H'
	DATATYPE_ZSET       = 's' // key => score
	DATATYPE_ZSCORE     = 'z' // key|score => ""
	DATATYPE_ZSIZE      = 'Z'
	DATATYPE_QUEUE      = 'q'
	DATATYPE_QSIZE      = 'Q'
	DATATYPE_MIN_PREFIX = DATATYPE_HASH
	DATATYPE_MAX_PREFIX = DATATYPE_ZSET

	BINLOGTYPE_NOOP     = 0
	BINLOGTYPE_SYNC     = 1
	BINLOGTYPE_MIRROR   = 2
	BINLOGTYPE_COPY     = 3
	BINLOGTYPE_CTRL     = 4

	BINLOGCOMMAND_NONE = 0
	BINLOGCOMMAND_KSET = 1
	BINLOGCOMMAND_KDEL = 2
	BINLOGCOMMAND_HSET = 3
	BINLOGCOMMAND_HDEL = 4
	BINLOGCOMMAND_ZSET = 5
	BINLOGCOMMAND_ZDEL = 6

	BINLOGCOMMAND_QPUSH_BACK  = 10
	BINLOGCOMMAND_QPUSH_FRONT = 11
	BINLOGCOMMAND_QPOP_BACK   = 12
	BINLOGCOMMAND_QPOP_FRONT  = 13
	BINLOGCOMMAND_QSET        = 14

	BINLOGCOMMAND_BEGIN = 7
	BINLOGCOMMAND_END   = 8

	SSDB_EXPIRATION_LIST_KEY = "\xff\xff\xff\xff\xff|EXPIRE_LIST|KV"
)

var (
	STATUS = map[uint32]string{
		0: "DISCONNECTED",
		1: "INIT",
		2: "COPY",
		4: "SYNC",
		8: "OUT_OF_SYNC",
	}

	DATATYPE = map[byte]string{
		byte('k'): "set",
		byte('h'): "hset",
		byte('s'): "zadd",
	}

	DATATRUECOMMAND = map[byte]string{
		byte(1): "set",
		byte(2): "del",
		byte(3): "hset",
		byte(4): "hdel",
		byte(5): "zset",
		byte(6): "zdel",
	}
)<commit_msg>add const variable of ssdb list<commit_after>package ssdb

const (
	SALVESTATUS_DISCONNECTED = 0
	SALVESTATUS_INIT = 1
	SALVESTATUS_COPY = 2
	SALVESTATUS_SYNC = 4
	SALVESTATUS_OUT_OF_SYNC = 8

	DATATYPE_SYNCLOG    = 1
	DATATYPE_KV         = 'k'
	DATATYPE_HASH       = 'h'
	DATATYPE_HSIZE      = 'H'
	DATATYPE_ZSET       = 's' // key => score
	DATATYPE_ZSCORE     = 'z' // key|score => ""
	DATATYPE_ZSIZE      = 'Z'
	DATATYPE_QUEUE      = 'q'
	DATATYPE_QSIZE      = 'Q'
	DATATYPE_MIN_PREFIX = DATATYPE_HASH
	DATATYPE_MAX_PREFIX = DATATYPE_ZSET

	BINLOGTYPE_NOOP     = 0
	BINLOGTYPE_SYNC     = 1
	BINLOGTYPE_MIRROR   = 2
	BINLOGTYPE_COPY     = 3
	BINLOGTYPE_CTRL     = 4

	BINLOGCOMMAND_NONE = 0
	BINLOGCOMMAND_KSET = 1
	BINLOGCOMMAND_KDEL = 2
	BINLOGCOMMAND_HSET = 3
	BINLOGCOMMAND_HDEL = 4
	BINLOGCOMMAND_ZSET = 5
	BINLOGCOMMAND_ZDEL = 6

	BINLOGCOMMAND_QPUSH_BACK  = 10
	BINLOGCOMMAND_QPUSH_FRONT = 11
	BINLOGCOMMAND_QPOP_BACK   = 12
	BINLOGCOMMAND_QPOP_FRONT  = 13
	BINLOGCOMMAND_QSET        = 14

	BINLOGCOMMAND_BEGIN = 7
	BINLOGCOMMAND_END   = 8

	SSDB_EXPIRATION_LIST_KEY = "\xff\xff\xff\xff\xff|EXPIRE_LIST|KV"
	SSDB_QFRONT_SEQ 	= int64(2)
	SSDB_QBACK_SEQ 		= int64(3)
	SSDB_QITEM_MIN_SEQ = int64(10000)
	SSDB_QITEM_MAX_SEQ = int64(9223372036854775807)
	SSDB_QITEM_SEQ_INIT = SSDB_QITEM_MAX_SEQ/2

)

var (
	STATUS = map[uint32]string{
		0: "DISCONNECTED",
		1: "INIT",
		2: "COPY",
		4: "SYNC",
		8: "OUT_OF_SYNC",
	}

	DATATYPE = map[byte]string{
		byte('k'): "set",
		byte('h'): "hset",
		byte('s'): "zadd",
	}

	DATATRUECOMMAND = map[byte]string{
		byte(1): "set",
		byte(2): "del",
		byte(3): "hset",
		byte(4): "hdel",
		byte(5): "zset",
		byte(6): "zdel",
	}
)<|endoftext|>


<commit_before>package parser

import (
	"github.com/modest-sql/common"
)

type statement interface {
	execute() error
	convert() interface{}
}

type statementList []statement

func (sl statementList) convert() (commands []interface{}) {
	for _, statement := range sl {
		command := statement.convert()

		if command != nil {
			commands = append(commands, command)
		}
	}
	return commands
}

func (sl statementList) execute() error {
	for _, statement := range sl {
		if err := statement.execute(); err != nil {
			panic(err)
		}
	}

	return nil
}

type createStatement struct {
	identifier        string
	columnDefinitions columnDefinitions
}

func (s *createStatement) convert() interface{} {
	return common.NewCreateTableCommand(s.identifier, s.columnDefinitions.convert())
}

func (s *createStatement) execute() error {
	return nil
}

type dropStatement struct {
	identifier string
}

func (s *dropStatement) convert() interface{} {
	return common.NewDropCommand(s.identifier)
}

func (s *dropStatement) execute() error {
	return nil
}

type insertStatement struct {
	table       string
	columnNames []string
	values      []interface{}
}

func (s *insertStatement) convert() interface{} {
	values := map[string]interface{}{}
	if len(s.columnNames) != len(s.values) {
		panic(true)
	}
	for i, columnName := range s.columnNames {
		values[columnName] = s.values[i]
	}

	return common.NewInsertCommand(s.table, values)
}

func (s *insertStatement) execute() error {
	return nil
}

type updateStatement struct {
	table           string
	assignments     []assignment
	whereExpression expression
}

func (s *updateStatement) convert() interface{} {
	return nil
}

func (s *updateStatement) execute() error {
	return nil
}

type deleteStatement struct {
	table           string
	alias           string
	whereExpression expression
}

func (s *deleteStatement) convert() interface{} {
	return nil
}

func (s *deleteStatement) execute() error {
	return nil
}

type columnSpec struct {
	isStar bool
	table  string
	column string
	alias  string
	function interface{}
}
type functionSum struct{

}
type functionCount struct{

}
type functionAvg struct{

}
type functionMin struct{

}
type functionMax struct{

}
type GroupBySpec struct{
	table string
	column  string
}

type selectStatement struct {
	selectColumns   []columnSpec
	mainTable string
	mainAlias string
	joinList []joinSpec
	whereExpression expression
	groupBy  []GroupBySpec
}

type joinSpec struct {
	targetTable string
	targetAlias string
	filterCriteria expression
}
func (s *selectStatement) convert() interface{} {
	return common.NewSelectTableCommand(s.mainTable)
}

func (s *selectStatement) execute() error {
	return nil
}

type alterStatement struct {
	table       string
	instruction interface{}
}

func (s *alterStatement) convert() interface{} {
	switch v := s.instruction.(type) {
	case *alterDrop:
		return common.NewAlterCommand(s.table, v.convert())
	case *alterAdd:
		return common.NewAlterCommand(s.table, v.convert())
	case *alterModify:
		return common.NewAlterCommand(s.table, v.convert())
	}
	return common.NewAlterCommand(s.table, nil)
}
func (s *alterStatement) execute() error {
	return nil
}

type alterDrop struct {
	table string
}

func (s *alterDrop) convert() interface{} {
	return common.NewAlterDropInst(s.table)
}
func (s *alterDrop) execute() error {
	return nil
}

type alterAdd struct {
	table             string
	dataType          dataType
	columnConstraints []interface{}
}

func (s *alterAdd) convert() interface{} {
	column := columnDefinition{s.table, s.dataType, s.columnConstraints}
	return common.NewAlterAddInst(column.convert())
}
func (s *alterAdd) execute() error {
	return nil
}

type alterModify struct {
	table             string
	dataType          dataType
	columnConstraints []interface{}
}

func (s *alterModify) convert() interface{} {
	column := columnDefinition{s.table, s.dataType, s.columnConstraints}
	return common.NewAlterModifyInst(column.convert())
}
func (s *alterModify) execute() error {
	return nil
}
<commit_msg>Added conversion logic for Update and Delete statments<commit_after>package parser

import (
	"github.com/modest-sql/common"
)

type statement interface {
	execute() error
	convert() interface{}
}

type statementList []statement

func (sl statementList) convert() (commands []interface{}) {
	for _, statement := range sl {
		command := statement.convert()

		if command != nil {
			commands = append(commands, command)
		}
	}
	return commands
}

func (sl statementList) execute() error {
	for _, statement := range sl {
		if err := statement.execute(); err != nil {
			panic(err)
		}
	}

	return nil
}

type createStatement struct {
	identifier        string
	columnDefinitions columnDefinitions
}

func (s *createStatement) convert() interface{} {
	return common.NewCreateTableCommand(s.identifier, s.columnDefinitions.convert())
}

func (s *createStatement) execute() error {
	return nil
}

type dropStatement struct {
	identifier string
}

func (s *dropStatement) convert() interface{} {
	return common.NewDropCommand(s.identifier)
}

func (s *dropStatement) execute() error {
	return nil
}

type insertStatement struct {
	table       string
	columnNames []string
	values      []interface{}
}

func (s *insertStatement) convert() interface{} {
	values := map[string]interface{}{}
	if len(s.columnNames) != len(s.values) {
		panic(true)
	}
	for i, columnName := range s.columnNames {
		values[columnName] = s.values[i]
	}

	return common.NewInsertCommand(s.table, values)
}

func (s *insertStatement) execute() error {
	return nil
}

type updateStatement struct {
	table           string
	assignments     []assignment
	whereExpression expression
}

func (s *updateStatement) convert() interface{} {
	var assCommon []common.AssignmentCommon
	for i, ass := range s.assignments {
		assCommon = append(assCommon, ass.convert())
	}
	return common.NewUpdateTableCommand(s.table, assCommon, whereExpression.convert() )
}

func (s *updateStatement) execute() error {
	return nil
}

type deleteStatement struct {
	table           string
	alias           string
	whereExpression expression
}

func (s *deleteStatement) convert() interface{} {
	return common.NewDeleteTableCommon(s.table, s.alias, s.whereExpression.convert())
}

func (s *deleteStatement) execute() error {
	return nil
}

type columnSpec struct {
	isStar bool
	table  string
	column string
	alias  string
	function interface{}
}
type functionSum struct{

}
type functionCount struct{

}
type functionAvg struct{

}
type functionMin struct{

}
type functionMax struct{

}
type GroupBySpec struct{
	table string
	column  string
}

type selectStatement struct {
	selectColumns   []columnSpec
	mainTable string
	mainAlias string
	joinList []joinSpec
	whereExpression expression
	groupBy  []GroupBySpec
}

type joinSpec struct {
	targetTable string
	targetAlias string
	filterCriteria expression
}
func (s *selectStatement) convert() interface{} {
	return common.NewSelectTableCommand(s.mainTable)
}

func (s *selectStatement) execute() error {
	return nil
}

type alterStatement struct {
	table       string
	instruction interface{}
}

func (s *alterStatement) convert() interface{} {
	switch v := s.instruction.(type) {
	case *alterDrop:
		return common.NewAlterCommand(s.table, v.convert())
	case *alterAdd:
		return common.NewAlterCommand(s.table, v.convert())
	case *alterModify:
		return common.NewAlterCommand(s.table, v.convert())
	}
	return common.NewAlterCommand(s.table, nil)
}
func (s *alterStatement) execute() error {
	return nil
}

type alterDrop struct {
	table string
}

func (s *alterDrop) convert() interface{} {
	return common.NewAlterDropInst(s.table)
}
func (s *alterDrop) execute() error {
	return nil
}

type alterAdd struct {
	table             string
	dataType          dataType
	columnConstraints []interface{}
}

func (s *alterAdd) convert() interface{} {
	column := columnDefinition{s.table, s.dataType, s.columnConstraints}
	return common.NewAlterAddInst(column.convert())
}
func (s *alterAdd) execute() error {
	return nil
}

type alterModify struct {
	table             string
	dataType          dataType
	columnConstraints []interface{}
}

func (s *alterModify) convert() interface{} {
	column := columnDefinition{s.table, s.dataType, s.columnConstraints}
	return common.NewAlterModifyInst(column.convert())
}
func (s *alterModify) execute() error {
	return nil
}
<|endoftext|>


<commit_before>package endly

import (
	"github.com/lunixbochs/vtclean"
	"strings"
	"unicode"
)

const commandNotFound = "command not found"
const noSuchFileOrDirectory = "no such file or directory"
const programCanBeFound = "can be found in the following packages"
const errorIsNotRecoverable = "Error is not recoverable"
const notInstalled = "not installed"
const canNotOpen = "Can't open"

//CheckNoSuchFileOrDirectory checks for no such file or directory message in the provided stdout.
func CheckNoSuchFileOrDirectory(stdout ...string) bool {
	if len(stdout) == 0 {
		return false
	}
	candidate := strings.ToLower(strings.Join(stdout, "\n"))
	return strings.Contains(candidate, noSuchFileOrDirectory)
}

//CheckCommandNotFound checks for command not found message in the provided stdout.
func CheckCommandNotFound(stdout ...string) bool {
	if len(stdout) == 0 {
		return false
	}
	candidate := strings.ToLower(strings.Join(stdout, "\n"))
	return strings.Contains(candidate, commandNotFound) || strings.Contains(candidate, notInstalled) || strings.Contains(candidate, canNotOpen)
}

//ExtractColumn extract a column from the line for provided index
func ExtractColumn(line string, columnIndex int) (string, bool) {
	var columns, has = ExtractColumns(line)
	if !has {
		return "", has
	}
	if columnIndex < len(columns) {
		return columns[columnIndex], true
	}
	return "", false
}

//ExtractColumns extract all column from the line
func ExtractColumns(line string) ([]string, bool) {
	if line == "" {
		return []string{}, false
	}
	var index = -1
	var expectColumn = true
	var result = make([]string, 0)
	for _, r := range line {
		if unicode.IsSpace(r) {
			expectColumn = true
			continue
		}
		if expectColumn {
			index++
			result = append(result, "")
			expectColumn = false
		}
		result[index] += vtclean.Clean(string(r), false)
	}
	return result, true
}

func escapeStdout(stdout string) string {
	return vtclean.Clean(stdout, true)
}
<commit_msg>patched ansi control sequence extraction from process status<commit_after>package endly

import (
	"github.com/lunixbochs/vtclean"
	"strings"
	"unicode"
)

const commandNotFound = "command not found"
const noSuchFileOrDirectory = "no such file or directory"
const programCanBeFound = "can be found in the following packages"
const errorIsNotRecoverable = "Error is not recoverable"
const notInstalled = "not installed"
const canNotOpen = "Can't open"

//CheckNoSuchFileOrDirectory checks for no such file or directory message in the provided stdout.
func CheckNoSuchFileOrDirectory(stdout ...string) bool {
	if len(stdout) == 0 {
		return false
	}
	candidate := strings.ToLower(strings.Join(stdout, "\n"))
	return strings.Contains(candidate, noSuchFileOrDirectory)
}

//CheckCommandNotFound checks for command not found message in the provided stdout.
func CheckCommandNotFound(stdout ...string) bool {
	if len(stdout) == 0 {
		return false
	}
	candidate := strings.ToLower(strings.Join(stdout, "\n"))
	return strings.Contains(candidate, commandNotFound) || strings.Contains(candidate, notInstalled) || strings.Contains(candidate, canNotOpen)
}

//ExtractColumn extract a column from the line for provided index
func ExtractColumn(line string, columnIndex int) (string, bool) {
	var columns, has = ExtractColumns(line)
	if !has {
		return "", has
	}
	if columnIndex < len(columns) {
		return columns[columnIndex], true
	}
	return "", false
}

//ExtractColumns extract all column from the line
func ExtractColumns(line string) ([]string, bool) {
	if line == "" {
		return []string{}, false
	}
	var index = -1
	var expectColumn = true
	var result = make([]string, 0)
	for _, r := range line {
		if unicode.IsSpace(r) {
			expectColumn = true
			continue
		}
		if expectColumn {
			index++
			result = append(result, "")
			expectColumn = false
		}

		result[index] += string(r)
	}

	for i, value := range result {
		result[i] = vtclean.Clean(value, false)
	}
	return result, true
}

func escapeStdout(stdout string) string {
	return vtclean.Clean(stdout, true)
}
<|endoftext|>


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

/*
Package stats contains support for OpenCensus stats collection.

OpenCensus allows users to create typed measures, record measurements,
aggregate the collected data, and export the aggregated data.

Measures

A measure represents a type of metric to be tracked and recorded.
For example, latency, request Mb/s, and response Mb/s are measures
to collect from a server.

Each measure needs to be registered before being used. Measure
constructors such as NewMeasureInt64 and NewMeasureFloat64 automatically
registers the measure by the given name. Each registered measure needs
to be unique by name. Measures also have a description and a unit.

Libraries can define and export measures for their end users to
create views and collect instrumentation data.

Recording measurements

Measurement is a data point to be collected for a measure. For example,
for a latency (ms) measure, 100 is a measurement that represents a 100ms
latency event. Users collect data points on the existing measures with
the current context. Tags from the current context is recorded with the
measurements if they are any.

Recorded measurements are dropped immediately if user is not aggregating
them via views. Users don't necessarily need to conditionally enable/disable
recording to reduce cost. Recording of measurements is cheap.

Libraries can always record measurements, and end-user can later decide
on which measurements they want to collect by registering views. This allows
libraries to turn on the instrumentation by default.

Views

In order to collect measurements, views need to be defined and registered.
A view allows recorded measurements to be filtered and aggregated over a time window.

All recorded measurements can be filtered by a list of tags.

OpenCensus provides two aggregation methods: count and distribution aggregation.
Count aggregation only counts the number of measurement points. Distribution
aggregation provides statistical summary of the aggregated data. Aggregation can
either happen cumulatively or over a sliding window.

Users can dynamically create and delete views.

Libraries can export their own views and claim the view names
by registering them themselves.

Exporting

Collected and aggregated data can be exported to a metric collection
backend by registering its exporter.

Multiple exporters can be registered to upload the data to various
different backends. Users need to unregister the exporters once they
no longer are needed.
*/
package stats // import "go.opencensus.io/stats"

// TODO(acetechnologist): Add a link to the language independent OpenCensus
// spec when it is available.
<commit_msg>Document the missing aggregation types (#220)<commit_after>// Copyright 2017, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/*
Package stats contains support for OpenCensus stats collection.

OpenCensus allows users to create typed measures, record measurements,
aggregate the collected data, and export the aggregated data.

Measures

A measure represents a type of metric to be tracked and recorded.
For example, latency, request Mb/s, and response Mb/s are measures
to collect from a server.

Each measure needs to be registered before being used. Measure
constructors such as NewMeasureInt64 and NewMeasureFloat64 automatically
registers the measure by the given name. Each registered measure needs
to be unique by name. Measures also have a description and a unit.

Libraries can define and export measures for their end users to
create views and collect instrumentation data.

Recording measurements

Measurement is a data point to be collected for a measure. For example,
for a latency (ms) measure, 100 is a measurement that represents a 100ms
latency event. Users collect data points on the existing measures with
the current context. Tags from the current context is recorded with the
measurements if they are any.

Recorded measurements are dropped immediately if user is not aggregating
them via views. Users don't necessarily need to conditionally enable/disable
recording to reduce cost. Recording of measurements is cheap.

Libraries can always record measurements, and end-user can later decide
on which measurements they want to collect by registering views. This allows
libraries to turn on the instrumentation by default.

Views

In order to collect measurements, views need to be defined and registered.
A view allows recorded measurements to be filtered and aggregated over a time window.

All recorded measurements can be filtered by a list of tags.

OpenCensus provides several aggregation methods: count, distribution, sum and mean.
Count aggregation only counts the number of measurement points. Distribution
aggregation provides statistical summary of the aggregated data. Sum distribution
sums up the measurement points. Mean provides the mean of the recorded measurements.
Aggregations can either happen cumulatively or over an interval.

Users can dynamically create and delete views.

Libraries can export their own views and claim the view names
by registering them themselves.

Exporting

Collected and aggregated data can be exported to a metric collection
backend by registering its exporter.

Multiple exporters can be registered to upload the data to various
different backends. Users need to unregister the exporters once they
no longer are needed.
*/
package stats // import "go.opencensus.io/stats"

// TODO(acetechnologist): Add a link to the language independent OpenCensus
// spec when it is available.
<|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 (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"v.io/x/lib/cmdline"
)

// TestV23TestGenerate tests that "v23 test generate" works as expected.  For
// each "golden" source directory under ./testdata/generate/* we copy the
// contents into a tmpdir, then run "v23 test generate" against that tmpdir, and
// finally compare the generated files against the golden source directory.
func TestV23TestGenerate(t *testing.T) {
	// Create a tmpdir where all generated files will go.
	tmpdir, err := ioutil.TempDir("", "v23_test_gen_")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	defer os.RemoveAll(tmpdir)
	// Set GOPATH so that the tmpdir appears first.
	oldGoPath := os.Getenv("GOPATH")
	newGoPath := strings.Join([]string{tmpdir, oldGoPath}, ":")
	if err := os.Setenv("GOPATH", newGoPath); err != nil {
		t.Fatalf(`Setenv("GOPATH", %q) failed: %v`, newGoPath, err)
	}
	defer os.Setenv("GOPATH", oldGoPath)
	// Read each test directory under ./testdata/generate.
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}
	gendir := filepath.Join(tmpdir, "src", "v.io", "x", "devtools", "v23", "testdata", "generate")
	srcdir := filepath.Join(cwd, "testdata", "generate")
	infos, err := ioutil.ReadDir(srcdir)
	if err != nil {
		t.Fatal(err)
	}
	// Test generation of each test directory.
	var testDirs []string
	for _, info := range infos {
		if !info.IsDir() {
			continue
		}
		testGenerate(t, gendir, srcdir, info.Name())
		testDirs = append(testDirs, info.Name())
	}
	// Make sure that we really ran the tests against all our test directories.
	if got, want := testDirs, []string{"empty", "external_only", "has_main", "internal_only", "internal_transitive_external", "modules_and_v23", "modules_only", "one", "prefix_other", "transitive", "v23_only"}; !reflect.DeepEqual(got, want) {
		t.Errorf("Ran tests against %v, want %v", got, want)
	}
}

func testGenerate(t *testing.T, gendir, srcdir, name string) {
	// Copy source files for "name" from srcdir to gendir.
	const pre = "prefix_"
	prefix := "v23"
	if strings.HasPrefix(name, pre) {
		prefix = name[len(pre):]
	}
	if err := copyAll(filepath.Join(gendir, name), filepath.Join(srcdir, name), prefix); err != nil {
		t.Fatal(err)
	}
	// Generate test files into gendir.
	env := cmdline.NewEnv()
	if err := cmdline.ParseAndRun(cmdTestGenerate, env, []string{"-prefix=" + prefix, "v.io/x/devtools/v23/testdata/generate/" + name}); err != nil {
		t.Fatal(err)
	}
	// Validate generated files.
	extFile := filepath.Join(name, prefix+externalSuffix)
	intFile := filepath.Join(name, prefix+internalSuffix)
	for _, f := range []string{extFile, intFile} {
		srcData, srcErr := ioutil.ReadFile(filepath.Join(srcdir, f))
		if srcErr != nil && !os.IsNotExist(srcErr) {
			t.Errorf("%s: Read src file failed: %v", f, srcErr)
		}
		genData, genErr := ioutil.ReadFile(filepath.Join(gendir, f))
		if genErr != nil && !os.IsNotExist(genErr) {
			t.Errorf("%s: Read gen file failed: %v", f, genErr)
		}
		if got, want := srcErr == nil, genErr == nil; got != want {
			t.Errorf("%s: Got src exist %v, want %v", f, got, want)
		}
		if got, want := srcData, genData; !bytes.Equal(got, want) {
			t.Errorf("%s: Got data %s, want %s", f, got, want)
		}
	}
}

// copyAll copies all files and directories from srcdir into dstdir, skipping
// generated files with the given prefix.
func copyAll(dstdir, srcdir, prefix string) error {
	if err := os.MkdirAll(dstdir, os.ModePerm); err != nil {
		return err
	}
	infos, err := ioutil.ReadDir(srcdir)
	if err != nil {
		return err
	}
	for _, info := range infos {
		name := info.Name()
		if name == prefix+externalSuffix || name == prefix+internalSuffix {
			// Skip generated files, based on the prefix.
			continue
		}
		dst, src := filepath.Join(dstdir, name), filepath.Join(srcdir, name)
		if info.IsDir() {
			// Copy directories recursively.
			return copyAll(dst, src, prefix)
		}
		// Copy files from src to dst.
		srcFile, err := os.Open(src)
		if err != nil {
			return err
		}
		dstFile, err := os.Create(dst)
		if err != nil {
			return err
		}
		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return err
		}
	}
	return nil
}

// TestV23TestGenerateTestdata runs "go test" against all packages under
// testdata/generate.  These are normally skipped since they're under a testdata
// directory.
func TestV23TestGenerateTestdata(t *testing.T) {
	var out bytes.Buffer
	env := &cmdline.Env{Stdout: &out, Stderr: &out}
	if err := runGo(env, []string{"test", "./testdata/generate/...", "-v", "-v23.tests"}); err != nil {
		t.Log(out.String())
		t.Errorf("tests under testdata/generate failed: %v", err)
	}
}
<commit_msg>devtools: Rename cmdline.NewEnv to cmdline.EnvFromOS<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 (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"testing"

	"v.io/x/lib/cmdline"
)

// TestV23TestGenerate tests that "v23 test generate" works as expected.  For
// each "golden" source directory under ./testdata/generate/* we copy the
// contents into a tmpdir, then run "v23 test generate" against that tmpdir, and
// finally compare the generated files against the golden source directory.
func TestV23TestGenerate(t *testing.T) {
	// Create a tmpdir where all generated files will go.
	tmpdir, err := ioutil.TempDir("", "v23_test_gen_")
	if err != nil {
		t.Fatalf("TempDir failed: %v", err)
	}
	defer os.RemoveAll(tmpdir)
	// Set GOPATH so that the tmpdir appears first.
	oldGoPath := os.Getenv("GOPATH")
	newGoPath := strings.Join([]string{tmpdir, oldGoPath}, ":")
	if err := os.Setenv("GOPATH", newGoPath); err != nil {
		t.Fatalf(`Setenv("GOPATH", %q) failed: %v`, newGoPath, err)
	}
	defer os.Setenv("GOPATH", oldGoPath)
	// Read each test directory under ./testdata/generate.
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatal(err)
	}
	gendir := filepath.Join(tmpdir, "src", "v.io", "x", "devtools", "v23", "testdata", "generate")
	srcdir := filepath.Join(cwd, "testdata", "generate")
	infos, err := ioutil.ReadDir(srcdir)
	if err != nil {
		t.Fatal(err)
	}
	// Test generation of each test directory.
	var testDirs []string
	for _, info := range infos {
		if !info.IsDir() {
			continue
		}
		testGenerate(t, gendir, srcdir, info.Name())
		testDirs = append(testDirs, info.Name())
	}
	// Make sure that we really ran the tests against all our test directories.
	if got, want := testDirs, []string{"empty", "external_only", "has_main", "internal_only", "internal_transitive_external", "modules_and_v23", "modules_only", "one", "prefix_other", "transitive", "v23_only"}; !reflect.DeepEqual(got, want) {
		t.Errorf("Ran tests against %v, want %v", got, want)
	}
}

func testGenerate(t *testing.T, gendir, srcdir, name string) {
	// Copy source files for "name" from srcdir to gendir.
	const pre = "prefix_"
	prefix := "v23"
	if strings.HasPrefix(name, pre) {
		prefix = name[len(pre):]
	}
	if err := copyAll(filepath.Join(gendir, name), filepath.Join(srcdir, name), prefix); err != nil {
		t.Fatal(err)
	}
	// Generate test files into gendir.
	env := cmdline.EnvFromOS()
	if err := cmdline.ParseAndRun(cmdTestGenerate, env, []string{"-prefix=" + prefix, "v.io/x/devtools/v23/testdata/generate/" + name}); err != nil {
		t.Fatal(err)
	}
	// Validate generated files.
	extFile := filepath.Join(name, prefix+externalSuffix)
	intFile := filepath.Join(name, prefix+internalSuffix)
	for _, f := range []string{extFile, intFile} {
		srcData, srcErr := ioutil.ReadFile(filepath.Join(srcdir, f))
		if srcErr != nil && !os.IsNotExist(srcErr) {
			t.Errorf("%s: Read src file failed: %v", f, srcErr)
		}
		genData, genErr := ioutil.ReadFile(filepath.Join(gendir, f))
		if genErr != nil && !os.IsNotExist(genErr) {
			t.Errorf("%s: Read gen file failed: %v", f, genErr)
		}
		if got, want := srcErr == nil, genErr == nil; got != want {
			t.Errorf("%s: Got src exist %v, want %v", f, got, want)
		}
		if got, want := srcData, genData; !bytes.Equal(got, want) {
			t.Errorf("%s: Got data %s, want %s", f, got, want)
		}
	}
}

// copyAll copies all files and directories from srcdir into dstdir, skipping
// generated files with the given prefix.
func copyAll(dstdir, srcdir, prefix string) error {
	if err := os.MkdirAll(dstdir, os.ModePerm); err != nil {
		return err
	}
	infos, err := ioutil.ReadDir(srcdir)
	if err != nil {
		return err
	}
	for _, info := range infos {
		name := info.Name()
		if name == prefix+externalSuffix || name == prefix+internalSuffix {
			// Skip generated files, based on the prefix.
			continue
		}
		dst, src := filepath.Join(dstdir, name), filepath.Join(srcdir, name)
		if info.IsDir() {
			// Copy directories recursively.
			return copyAll(dst, src, prefix)
		}
		// Copy files from src to dst.
		srcFile, err := os.Open(src)
		if err != nil {
			return err
		}
		dstFile, err := os.Create(dst)
		if err != nil {
			return err
		}
		if _, err := io.Copy(dstFile, srcFile); err != nil {
			return err
		}
	}
	return nil
}

// TestV23TestGenerateTestdata runs "go test" against all packages under
// testdata/generate.  These are normally skipped since they're under a testdata
// directory.
func TestV23TestGenerateTestdata(t *testing.T) {
	var out bytes.Buffer
	env := &cmdline.Env{Stdout: &out, Stderr: &out}
	if err := runGo(env, []string{"test", "./testdata/generate/...", "-v", "-v23.tests"}); err != nil {
		t.Log(out.String())
		t.Errorf("tests under testdata/generate failed: %v", err)
	}
}
<|endoftext|>


<commit_before>package keygen

import (
	"crypto/rand"
	"errors"
	"github.com/northbright/errorhelper"
	"github.com/northbright/pathhelper"
	"io/ioutil"
	"os"
)

const (
	KeySizeError string = "Key size error" // Key size error message.
)

// GenSymmetricKey() generates key byte array for symmetric key alogorithm like HMAC.
//
//   Params:
//       size: Key size in bits. Ex: 256 bits for HMAC SHA-256 and 512 bits for HMAC SHA-512.
//   Return:
//       k: Key stored in byte array.
//       err: error.
func GenSymmetricKey(bits int) (k []byte, err error) {
	if bits <= 0 || bits%8 != 0 {
		return nil, errors.New(KeySizeError)
	}

	size := bits / 8
	k = make([]byte, size)
	if _, err = rand.Read(k); err != nil {
		return nil, err
	}

	return k, nil
}

// GenSymmetricKeyFile() generates key file for symmetric key alogrithm like HMAC.
//
//   Params:
//       size: Key size in bits. Ex: 256 bits for HMAC SHA-256 and 512 bits for HMAC SHA-512.
//       outputFile: Output key file.
//       perm: Permission of key file. The final permission of file will be perm - umask. Ex: 0666 - 002(centos) = 0644.
//   Return:
//       err: error.
func GenSymmetricKeyFile(bits int, outputFile string, perm os.FileMode) (err error) {
	if err = errorhelper.GenEmptyStringError(outputFile, "outputFile"); err != nil {
		return err
	}

	p := ""
	if p, err = pathhelper.GetAbsPath(outputFile); err != nil {
		return err
	}

	k, err := GenSymmetricKey(bits)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(p, k, perm)
}
<commit_msg>Fix type for umask substraction<commit_after>package keygen

import (
	"crypto/rand"
	"errors"
	"github.com/northbright/errorhelper"
	"github.com/northbright/pathhelper"
	"io/ioutil"
	"os"
)

const (
	KeySizeError string = "Key size error" // Key size error message.
)

// GenSymmetricKey() generates key byte array for symmetric key alogorithm like HMAC.
//
//   Params:
//       size: Key size in bits. Ex: 256 bits for HMAC SHA-256 and 512 bits for HMAC SHA-512.
//   Return:
//       k: Key stored in byte array.
//       err: error.
func GenSymmetricKey(bits int) (k []byte, err error) {
	if bits <= 0 || bits%8 != 0 {
		return nil, errors.New(KeySizeError)
	}

	size := bits / 8
	k = make([]byte, size)
	if _, err = rand.Read(k); err != nil {
		return nil, err
	}

	return k, nil
}

// GenSymmetricKeyFile() generates key file for symmetric key alogrithm like HMAC.
//
//   Params:
//       size: Key size in bits. Ex: 256 bits for HMAC SHA-256 and 512 bits for HMAC SHA-512.
//       outputFile: Output key file.
//       perm: Permission of key file. The final permission of file will be perm - umask. Ex: 0666 - 002(centos) = 0664.
//   Return:
//       err: error.
func GenSymmetricKeyFile(bits int, outputFile string, perm os.FileMode) (err error) {
	if err = errorhelper.GenEmptyStringError(outputFile, "outputFile"); err != nil {
		return err
	}

	p := ""
	if p, err = pathhelper.GetAbsPath(outputFile); err != nil {
		return err
	}

	k, err := GenSymmetricKey(bits)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(p, k, perm)
}
<|endoftext|>


<commit_before>package fasthttp

import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

// TCP dialers used by client.
//
// These dialers are intended for custom code wrapping before passing
// to Client.Dial or HostClient.Dial.
//
// For instance, per-host counters and/or limits may be implemented
// by such wrappers.
//
// The addr paseed to dial func may contain port. Example addr values:
//
//     * google.com
//     * foobar.baz:443
//     * foo.bar:80
//     * aaa.com:8080
//
// Default port is appended to the addr if port is missing:
//
//     * ':80' if Dial is used
//     * ':443' if DialTLS is used
var (
	// Dial dials the given addr using tcp4.
	// '80' port is used if port is missing in the addr passed to the func.
	Dial = DialFunc((&tcpDialer{}).NewDial())

	// DialTLS dials the given addr using tcp4.
	// '443' port is used if port is missing in the addr passed to the func.
	DialTLS = DialFunc((&tcpDialer{IsTLS: true}).NewDial())

	// DialDualStack dials the given addr using both tcp4 and tcp6.
	// '80' port is used if port is missing in the addr passed to the func.
	DialDualStack = DialFunc((&tcpDialer{DualStack: true}).NewDial())

	// DialTLSDualStack dials the given addr using both tcp4 and tcp6.
	// '443' port is used if port is missing in the addr passed to the func.
	DialTLSDualStack = DialFunc((&tcpDialer{IsTLS: true, DualStack: true}).NewDial())
)

// tcpDialer implements default TCP dialer for the Client and HostClient.
//
// tcpDialer instance copying is forbiddent. Create new instance instead.
type tcpDialer struct {
	// Appends ':80' to the addr with missing port in Dial if set to false.
	// Appends ':443' to the addr with missing port in Dial if set to true.
	IsTLS bool

	// Set to true if you want simultaneously dialing tcp4 and tcp6.
	DualStack bool

	tcpAddrsLock sync.Mutex
	tcpAddrsMap  map[string]*tcpAddrEntry
}

func (d *tcpDialer) NewDial() DialFunc {
	if d.tcpAddrsMap != nil {
		panic("BUG: NewDial() already called")
	}

	d.tcpAddrsMap = make(map[string]*tcpAddrEntry)
	go d.tcpAddrsClean()

	return func(addr string) (net.Conn, error) {
		tcpAddr, err := d.getTCPAddr(addr)
		if err != nil {
			return nil, err
		}
		network := "tcp4"
		if d.DualStack {
			network = "tcp"
		}
		return net.DialTCP(network, nil, tcpAddr)
	}
}

type tcpAddrEntry struct {
	addrs    []net.TCPAddr
	addrsIdx uint32

	resolveTime time.Time
	pending     bool
}

var tcpAddrsCacheDuration = time.Minute

func (d *tcpDialer) tcpAddrsClean() {
	expireDuration := 2 * tcpAddrsCacheDuration
	for {
		time.Sleep(time.Second)
		t := time.Now()

		d.tcpAddrsLock.Lock()
		for k, e := range d.tcpAddrsMap {
			if t.Sub(e.resolveTime) > expireDuration {
				delete(d.tcpAddrsMap, k)
			}
		}
		d.tcpAddrsLock.Unlock()
	}
}

func (d *tcpDialer) getTCPAddr(addr string) (*net.TCPAddr, error) {
	addr = addMissingPort(addr, d.IsTLS)

	d.tcpAddrsLock.Lock()
	e := d.tcpAddrsMap[addr]
	if e != nil && !e.pending && time.Since(e.resolveTime) > tcpAddrsCacheDuration {
		e.pending = true
		e = nil
	}
	d.tcpAddrsLock.Unlock()

	if e == nil {
		tcpAddrs, err := resolveTCPAddrs(addr, d.DualStack)
		if err != nil {
			d.tcpAddrsLock.Lock()
			e = d.tcpAddrsMap[addr]
			if e != nil && e.pending {
				e.pending = false
			}
			d.tcpAddrsLock.Unlock()
			return nil, err
		}

		e = &tcpAddrEntry{
			addrs:       tcpAddrs,
			resolveTime: time.Now(),
		}

		d.tcpAddrsLock.Lock()
		d.tcpAddrsMap[addr] = e
		d.tcpAddrsLock.Unlock()
	}

	tcpAddr := &e.addrs[0]
	n := len(e.addrs)
	if n > 1 {
		n := atomic.AddUint32(&e.addrsIdx, 1)
		tcpAddr = &e.addrs[n%uint32(n)]
	}
	return tcpAddr, nil
}

func addMissingPort(addr string, isTLS bool) string {
	n := strings.Index(addr, ":")
	if n >= 0 {
		return addr
	}
	port := 80
	if isTLS {
		port = 443
	}
	return fmt.Sprintf("%s:%d", addr, port)
}

func resolveTCPAddrs(addr string, dualStack bool) ([]net.TCPAddr, error) {
	host, portS, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, err
	}
	port, err := strconv.Atoi(portS)
	if err != nil {
		return nil, err
	}

	ips, err := net.LookupIP(host)
	if err != nil {
		return nil, err
	}

	n := len(ips)
	addrs := make([]net.TCPAddr, 0, n)
	for i := 0; i < n; i++ {
		ip := ips[i]
		if !dualStack && ip.To4() == nil {
			continue
		}
		addrs = append(addrs, net.TCPAddr{
			IP:   ip,
			Port: port,
		})
	}
	return addrs, nil
}
<commit_msg>typo fix<commit_after>package fasthttp

import (
	"fmt"
	"net"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

// TCP dialers used by client.
//
// These dialers are intended for custom code wrapping before passing
// to Client.Dial or HostClient.Dial.
//
// For instance, per-host counters and/or limits may be implemented
// by such wrappers.
//
// The addr passed to dial func may contain port. Example addr values:
//
//     * google.com
//     * foobar.baz:443
//     * foo.bar:80
//     * aaa.com:8080
//
// Default port is appended to the addr if port is missing:
//
//     * ':80' if Dial is used
//     * ':443' if DialTLS is used
var (
	// Dial dials the given addr using tcp4.
	// '80' port is used if port is missing in the addr passed to the func.
	Dial = DialFunc((&tcpDialer{}).NewDial())

	// DialTLS dials the given addr using tcp4.
	// '443' port is used if port is missing in the addr passed to the func.
	DialTLS = DialFunc((&tcpDialer{IsTLS: true}).NewDial())

	// DialDualStack dials the given addr using both tcp4 and tcp6.
	// '80' port is used if port is missing in the addr passed to the func.
	DialDualStack = DialFunc((&tcpDialer{DualStack: true}).NewDial())

	// DialTLSDualStack dials the given addr using both tcp4 and tcp6.
	// '443' port is used if port is missing in the addr passed to the func.
	DialTLSDualStack = DialFunc((&tcpDialer{IsTLS: true, DualStack: true}).NewDial())
)

// tcpDialer implements default TCP dialer for the Client and HostClient.
//
// tcpDialer instance copying is forbiddent. Create new instance instead.
type tcpDialer struct {
	// Appends ':80' to the addr with missing port in Dial if set to false.
	// Appends ':443' to the addr with missing port in Dial if set to true.
	IsTLS bool

	// Set to true if you want simultaneously dialing tcp4 and tcp6.
	DualStack bool

	tcpAddrsLock sync.Mutex
	tcpAddrsMap  map[string]*tcpAddrEntry
}

func (d *tcpDialer) NewDial() DialFunc {
	if d.tcpAddrsMap != nil {
		panic("BUG: NewDial() already called")
	}

	d.tcpAddrsMap = make(map[string]*tcpAddrEntry)
	go d.tcpAddrsClean()

	return func(addr string) (net.Conn, error) {
		tcpAddr, err := d.getTCPAddr(addr)
		if err != nil {
			return nil, err
		}
		network := "tcp4"
		if d.DualStack {
			network = "tcp"
		}
		return net.DialTCP(network, nil, tcpAddr)
	}
}

type tcpAddrEntry struct {
	addrs    []net.TCPAddr
	addrsIdx uint32

	resolveTime time.Time
	pending     bool
}

var tcpAddrsCacheDuration = time.Minute

func (d *tcpDialer) tcpAddrsClean() {
	expireDuration := 2 * tcpAddrsCacheDuration
	for {
		time.Sleep(time.Second)
		t := time.Now()

		d.tcpAddrsLock.Lock()
		for k, e := range d.tcpAddrsMap {
			if t.Sub(e.resolveTime) > expireDuration {
				delete(d.tcpAddrsMap, k)
			}
		}
		d.tcpAddrsLock.Unlock()
	}
}

func (d *tcpDialer) getTCPAddr(addr string) (*net.TCPAddr, error) {
	addr = addMissingPort(addr, d.IsTLS)

	d.tcpAddrsLock.Lock()
	e := d.tcpAddrsMap[addr]
	if e != nil && !e.pending && time.Since(e.resolveTime) > tcpAddrsCacheDuration {
		e.pending = true
		e = nil
	}
	d.tcpAddrsLock.Unlock()

	if e == nil {
		tcpAddrs, err := resolveTCPAddrs(addr, d.DualStack)
		if err != nil {
			d.tcpAddrsLock.Lock()
			e = d.tcpAddrsMap[addr]
			if e != nil && e.pending {
				e.pending = false
			}
			d.tcpAddrsLock.Unlock()
			return nil, err
		}

		e = &tcpAddrEntry{
			addrs:       tcpAddrs,
			resolveTime: time.Now(),
		}

		d.tcpAddrsLock.Lock()
		d.tcpAddrsMap[addr] = e
		d.tcpAddrsLock.Unlock()
	}

	tcpAddr := &e.addrs[0]
	n := len(e.addrs)
	if n > 1 {
		n := atomic.AddUint32(&e.addrsIdx, 1)
		tcpAddr = &e.addrs[n%uint32(n)]
	}
	return tcpAddr, nil
}

func addMissingPort(addr string, isTLS bool) string {
	n := strings.Index(addr, ":")
	if n >= 0 {
		return addr
	}
	port := 80
	if isTLS {
		port = 443
	}
	return fmt.Sprintf("%s:%d", addr, port)
}

func resolveTCPAddrs(addr string, dualStack bool) ([]net.TCPAddr, error) {
	host, portS, err := net.SplitHostPort(addr)
	if err != nil {
		return nil, err
	}
	port, err := strconv.Atoi(portS)
	if err != nil {
		return nil, err
	}

	ips, err := net.LookupIP(host)
	if err != nil {
		return nil, err
	}

	n := len(ips)
	addrs := make([]net.TCPAddr, 0, n)
	for i := 0; i < n; i++ {
		ip := ips[i]
		if !dualStack && ip.To4() == nil {
			continue
		}
		addrs = append(addrs, net.TCPAddr{
			IP:   ip,
			Port: port,
		})
	}
	return addrs, nil
}
<|endoftext|>


<commit_before>package hpcloud

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

var REGION_URL = "https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/"

func Authenticate(user, pass string) *Access {
	l := Login{auth{credentials{User: user, Pass: pass}}}
	d, err := json.Marshal(l)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	fmt.Println(string(d))
	resp, err := http.Post(REGION_URL+"tokens", "application/json", strings.NewReader(string(d)))
	if err != nil {
		fmt.Println(err)
		return nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	a := &Access{}
	err = json.Unmarshal(body, a)
	fmt.Println(string(body))
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return a
}
<commit_msg>Removed debug statements.<commit_after>package hpcloud

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

var REGION_URL = "https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/"

func Authenticate(user, pass string) *Access {
	l := Login{auth{credentials{User: user, Pass: pass}}}
	d, err := json.Marshal(l)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	resp, err := http.Post(REGION_URL+"tokens", "application/json", strings.NewReader(string(d)))
	if err != nil {
		fmt.Println(err)
		return nil
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	a := &Access{}
	err = json.Unmarshal(body, a)
	if err != nil {
		fmt.Println(err)
		return nil
	}
	return a
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"strconv"

	"github.com/bullyork/serviceGen/src/tool"
)

type schema struct {
	syntax   int
	imports  []interface{}
	enums    []int
	messages []message
	options  map[string]interface{}
	extends  []interface{}
	pack     string
}

type tokensArray struct {
	data []string
}

func onfieldoptions(tokens *tokensArray) map[string]string {
	var opts map[string]string
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "[", ",":
			shift(tokens)
			name := shift(tokens)
			if name == "(" {
				name = shift(tokens)
				shift(tokens)
			}
			if tokens.data[0] != "=" {
				fmt.Println("Unexpected token in field options: " + tokens.data[0])
			}
			shift(tokens)
			if tokens.data[0] == "]" {
				fmt.Println("Unexpected ] in field option")
			}
			opts["name"] = shift(tokens)
		case "]":
			shift(tokens)
			return opts
		default:
			fmt.Println("Unexpected token in field options: " + tokens.data[0])
		}
	}
	fmt.Println("No closing tag for field options")
	return opts
}

func onpackagename(tokens *tokensArray) string {
	shift(tokens)
	name := tokens.data[0]
	shift(tokens)
	if tokens.data[0] != ";" {
		fmt.Println("Expected ; but found " + tokens.data[0])
	}
	shift(tokens)
	return name
}

func onsyntaxversion(tokens *tokensArray) int {
	shift(tokens)
	if tokens.data[0] != "=" {
		fmt.Println("Expected = but found " + tokens.data[0])
	}
	shift(tokens)
	versionStr := tokens.data[0]
	var version int
	shift(tokens)
	switch versionStr {
	case `"proto2"`:
		version = 2
	case `"proto3"`:
		version = 3
	default:
		fmt.Println("Expected protobuf syntax version but found " + versionStr)
	}
	if tokens.data[0] != ";" {
		fmt.Println("Expected ; but found " + tokens.data[0])
	}
	shift(tokens)
	return version
}

type message struct {
	name     string
	enums    []int
	extends  []string
	messages []string
	fields   []string
}

type field struct {
	name     string
	typeArea string
	tag      int
	mapArea  map[string]string
	required bool
	repeated bool
	options  map[string]string
}

type messageBody struct {
	enums      []int
	messages   []string
	fields     []field
	extends    []string
	extensions extensions
}

type extensions struct {
	from int
	to   int
}

func onfield(tokens *tokensArray) field {
	var field field
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "=":
			shift(tokens)
			if v, err := strconv.Atoi(shift(tokens)); err == nil {
				field.tag = v
			} else {
				fmt.Println(err)
			}
		case "map":
			field.typeArea = "map"
			shift(tokens)
			if tokens.data[0] != "<" {
				fmt.Println(`Unexpected token in map type: ` + tokens.data[0])
			}
			shift(tokens)
			field.mapArea["from"] = shift(tokens)
			if tokens.data[0] != "," {
				fmt.Println(`Unexpected token in map type: ` + tokens.data[0])
			}
			shift(tokens)
			field.mapArea["to"] = shift(tokens)
			if tokens.data[0] != ">" {
				fmt.Println(`Unexpected token in map type: ` + tokens.data[0])
			}
			shift(tokens)
			field.name = shift(tokens)
		case "repeated", "required", "optional":
			var t = shift(tokens)
			field.required = (t == "required")
			field.repeated = (t == "repeated")
			field.typeArea = shift(tokens)
			field.name = shift(tokens)
		case "[":
			field.options = onfieldoptions(tokens)
		case ";":
			if field.name == "" {
				fmt.Println("Missing field name")
			}
			if field.typeArea == "" {
				fmt.Println("Missing type in message field: " + field.name)
			}
			if field.tag == -1 {
				fmt.Println("Missing tag number in message field: " + field.name)
			}
			shift(tokens)
			return field
		default:
			fmt.Println("Unexpected token in message field: " + tokens.data[0])
		}
	}
	fmt.Println("No ; found for message field")
	return field
}

func onenum(tokens *tokensArray) map[string]interface{} {
	shift(tokens)
	var e map[string]interface{}
	e["name"] = shift(tokens)
	if tokens.data[0] != "{" {
		fmt.Println("Expected { but found " + tokens.data[0])
	}
	shift(tokens)
	for len(tokens.data) > 0 {
		if tokens.data[0] == "}" {
			shift(tokens)
			if tokens.data[0] == ";" {
				shift(tokens)
			}
			return e
		}
	}
}

func onmessagebody(tokens *tokensArray) messageBody {
	var body messageBody
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "map", "repeated", "optional", "required":
			append(body.fields, onfield(tokens))
		case "enum":
			body.enums.push(onenum(tokens))
		}
	}
}

func onmessage(tokens *tokensArray) message {
	shift(tokens)
	lvl := 1
	var bodyTokens tokensArray
	var msg message
	msg.name = shift(tokens)
	if tokens.data[0] != "{" {
		fmt.Println(`Expected { but found '` + tokens.data[0])
	}
	shift(tokens)
	for len(tokens.data) > 0 {
		if tokens.data[0] == "{" {
			lvl++
		} else if tokens.data[0] == "}" {
			lvl--
		}
		if lvl == 0 {
			shift(tokens)
			body = onmessagebody(*bodyTokens)
			msg.enums = body.enums
			msg.messages = body.messages
			msg.fields = body.fields
			msg.extends = body.extends
			msg.extensions = body.extensions
			return msg
		}
		bodyTokens.data = append(bodyTokens.data, shift(tokens))
	}
}

func shift(tokens *tokensArray) string {
	str := tokens.data[0]
	tokens.data = tokens.data[1:]
	return str
}

func main() {
	var tokens tokensArray
	tokens.data = tool.Token("../proto/express/common.proto")

	var sch schema
	firstline := true
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "package":
			sch.pack = onpackagename(&tokens)
		case "syntax":
			sch.syntax = onsyntaxversion(&tokens)
		case "message":
			append(sch.messages, onmessage(&tokens))
		}
	}
}
<commit_msg>增加parse函数<commit_after>package main

import (
	"fmt"
	"reflect"
	"regexp"
	"strconv"

	"github.com/bullyork/serviceGen/src/tool"
)

type schema struct {
	syntax   int
	imports  []interface{}
	enums    []int
	messages []message
	options  map[string]interface{}
	extends  []interface{}
	pack     string
}

type tokensArray struct {
	data []string
}

func onfieldoptions(tokens *tokensArray) map[string]string {
	var opts map[string]string
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "[", ",":
			shift(tokens)
			name := shift(tokens)
			if name == "(" {
				name = shift(tokens)
				shift(tokens)
			}
			if tokens.data[0] != "=" {
				fmt.Println("Unexpected token in field options: " + tokens.data[0])
			}
			shift(tokens)
			if tokens.data[0] == "]" {
				fmt.Println("Unexpected ] in field option")
			}
			opts["name"] = shift(tokens)
		case "]":
			shift(tokens)
			return opts
		default:
			fmt.Println("Unexpected token in field options: " + tokens.data[0])
		}
	}
	fmt.Println("No closing tag for field options")
	return opts
}

func onpackagename(tokens *tokensArray) string {
	shift(tokens)
	name := tokens.data[0]
	shift(tokens)
	if tokens.data[0] != ";" {
		fmt.Println("Expected ; but found " + tokens.data[0])
	}
	shift(tokens)
	return name
}

func onsyntaxversion(tokens *tokensArray) int {
	shift(tokens)
	if tokens.data[0] != "=" {
		fmt.Println("Expected = but found " + tokens.data[0])
	}
	shift(tokens)
	versionStr := tokens.data[0]
	var version int
	shift(tokens)
	switch versionStr {
	case `"proto2"`:
		version = 2
	case `"proto3"`:
		version = 3
	default:
		fmt.Println("Expected protobuf syntax version but found " + versionStr)
	}
	if tokens.data[0] != ";" {
		fmt.Println("Expected ; but found " + tokens.data[0])
	}
	shift(tokens)
	return version
}

type message struct {
	name     string
	enums    []int
	extends  []string
	messages []string
	fields   []string
}

type field struct {
	name     string
	typeArea string
	tag      int
	mapArea  map[string]string
	required bool
	repeated bool
	options  map[string]string
}

type messageBody struct {
	enums      []int
	messages   []string
	fields     []field
	extends    []string
	extensions extensions
}

type extensions struct {
	from int
	to   int
}

func onfield(tokens *tokensArray) field {
	var field field
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "=":
			shift(tokens)
			if v, err := strconv.Atoi(shift(tokens)); err == nil {
				field.tag = v
			} else {
				fmt.Println(err)
			}
		case "map":
			field.typeArea = "map"
			shift(tokens)
			if tokens.data[0] != "<" {
				fmt.Println(`Unexpected token in map type: ` + tokens.data[0])
			}
			shift(tokens)
			field.mapArea["from"] = shift(tokens)
			if tokens.data[0] != "," {
				fmt.Println(`Unexpected token in map type: ` + tokens.data[0])
			}
			shift(tokens)
			field.mapArea["to"] = shift(tokens)
			if tokens.data[0] != ">" {
				fmt.Println(`Unexpected token in map type: ` + tokens.data[0])
			}
			shift(tokens)
			field.name = shift(tokens)
		case "repeated", "required", "optional":
			var t = shift(tokens)
			field.required = (t == "required")
			field.repeated = (t == "repeated")
			field.typeArea = shift(tokens)
			field.name = shift(tokens)
		case "[":
			field.options = onfieldoptions(tokens)
		case ";":
			if field.name == "" {
				fmt.Println("Missing field name")
			}
			if field.typeArea == "" {
				fmt.Println("Missing type in message field: " + field.name)
			}
			if field.tag == -1 {
				fmt.Println("Missing tag number in message field: " + field.name)
			}
			shift(tokens)
			return field
		default:
			fmt.Println("Unexpected token in message field: " + tokens.data[0])
		}
	}
	fmt.Println("No ; found for message field")
	return field
}

func parse(value string) interface{} {
	if value == "true" {
		return true
	}
	if value == "false" {
		return false
	}
	return value
}

func toSlice(arr interface{}) []interface{} {
	v := reflect.ValueOf(arr)
	if v.Kind() != reflect.Slice {
		panic("toslice arr not slice")
	}
	l := v.Len()
	ret := make([]interface{}, l)
	for i := 0; i < l; i++ {
		ret[i] = v.Index(i).Interface()
	}
	return ret
}

func onoptionMap(tokens *tokensArray) interface{} {
	var result map[string]interface{}
	for len(tokens.data) > 0 {
		if tokens.data[0] == "}" {
			shift(tokens)
			return result
		}
		hasBracket := tokens.data[0] == "("
		if hasBracket {
			shift(tokens)
		}
		key := shift(tokens)
		if hasBracket {
			if tokens.data[0] != ")" {
				fmt.Println("Expected ) but found " + tokens.data[0])
			}
		}
		var value interface{}
		switch tokens.data[0] {
		case ":":
			if result[key] != nil {
				fmt.Println("Duplicate option map key " + key)
			}
			shift(tokens)
			value = parse(shift(tokens))
			if value.(string) == "{" {
				value = onoptionMap(tokens)
			}
			result[key] = value
		case "{":
			shift(tokens)
			value = onoptionMap(tokens)
			if result[key] == nil {
				var s = make([]interface{}, 0)
				result[key] = s
			}
			v := reflect.ValueOf(result[key])
			if v.Kind() != reflect.Slice {
				fmt.Println("Duplicate option map key " + key)
			}
			l := v.Len()
			sliceValue := make([]interface{}, l)
			for i := 0; i < l; i++ {
				sliceValue[i] = v.Index(i).Interface()
			}
			result[key] = append(sliceValue, value)
		default:
			fmt.Println("Unexpected token in option map: " + tokens.data[0])
		}
	}
	fmt.Println("No closing tag for option map")
	return result
}

func onoption(tokens *tokensArray) map[string]interface{} {
	var name string
	var value interface{}
	var result map[string]interface{}
	for len(tokens.data) > 0 {
		if tokens.data[0] == ";" {
			shift(tokens)
			result["name"] = name
			result["value"] = value
			return result
		}
		switch tokens.data[0] {
		case "option":
			shift(tokens)
			hasBracket := tokens.data[0] == "("
			if hasBracket {
				shift(tokens)
			}
			name = shift(tokens)
			if hasBracket {
				if tokens.data[0] != ")" {
					fmt.Println("Expected ) but found " + tokens.data[0])
				}
				shift(tokens)
			}
		case "=":
			shift(tokens)
			if name == "" {
				fmt.Println("Expected key for option with value: " + tokens.data[0])
			}
			value = parse(shift(tokens))
			re, _ := regexp.Compile(`^(SPEED|CODE_SIZE|LITE_RUNTIME)$`)
			flag := re.MatchString(value.(string))
			if name == "optimize_for" && !flag {
				fmt.Println("Unexpected value for option optimize_for: " + value.(string))
			} else if value.(string) == "{" {
				value = onoptionMap(tokens)
			}
		default:
			fmt.Println("Unexpected token in option: " + tokens.data[0])
		}
	}
	return result
}

func onenum(tokens *tokensArray) map[string]interface{} {
	shift(tokens)
	var e map[string]interface{}
	e["name"] = shift(tokens)
	if tokens.data[0] != "{" {
		fmt.Println("Expected { but found " + tokens.data[0])
	}
	shift(tokens)
	for len(tokens.data) > 0 {
		if tokens.data[0] == "}" {
			shift(tokens)
			if tokens.data[0] == ";" {
				shift(tokens)
			}
			return e
		}
		if tokens.data[0] == "option" {
			options := onoption(tokens)
		}
	}
}

func onmessagebody(tokens *tokensArray) messageBody {
	var body messageBody
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "map", "repeated", "optional", "required":
			append(body.fields, onfield(tokens))
		case "enum":
			body.enums.push(onenum(tokens))
		}
	}
}

func onmessage(tokens *tokensArray) message {
	shift(tokens)
	lvl := 1
	var bodyTokens tokensArray
	var msg message
	msg.name = shift(tokens)
	if tokens.data[0] != "{" {
		fmt.Println(`Expected { but found '` + tokens.data[0])
	}
	shift(tokens)
	for len(tokens.data) > 0 {
		if tokens.data[0] == "{" {
			lvl++
		} else if tokens.data[0] == "}" {
			lvl--
		}
		if lvl == 0 {
			shift(tokens)
			body = onmessagebody(*bodyTokens)
			msg.enums = body.enums
			msg.messages = body.messages
			msg.fields = body.fields
			msg.extends = body.extends
			msg.extensions = body.extensions
			return msg
		}
		bodyTokens.data = append(bodyTokens.data, shift(tokens))
	}
}

func shift(tokens *tokensArray) string {
	str := tokens.data[0]
	tokens.data = tokens.data[1:]
	return str
}

func main() {
	var tokens tokensArray
	tokens.data = tool.Token("../proto/express/common.proto")

	var sch schema
	firstline := true
	for len(tokens.data) > 0 {
		switch tokens.data[0] {
		case "package":
			sch.pack = onpackagename(&tokens)
		case "syntax":
			sch.syntax = onsyntaxversion(&tokens)
		case "message":
			append(sch.messages, onmessage(&tokens))
		}
	}
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Romain LÉTENDART
//
// See LICENSE file.

// Package core contains the bot's core functionalities
package core

import (
	"github.com/thoj/go-ircevent"
	"log"
	"strings"
)

var (
	updateAdminsDone = make(chan bool, 1)
)

// Bot structure that contains connection informations, IRC connection, command handlers and message handlers
type Bot struct {
	nick              string
	server            string
	channel           string
	channelKey        string
	Admins            *[]string
	ircConn           *irc.Connection
	msgHandlers       []func(*irc.Event, func(*ReplyCallbackData))
	msgReplyCallbacks []func(*ReplyCallbackData)
	cmdHandlers       map[string]func(*irc.Event, func(*ReplyCallbackData)) bool
	cmdReplyCallbacks map[string]func(*ReplyCallbackData)
}

// ReplyCallbackData Structure used by the handlers to send data in a standardized format
type ReplyCallbackData struct {
	Message string // Message to send
	Target  string // Destination target of the message (Channel or Nick)
}

// Command structure
type Command struct {
	Module      string
	HelpMessage string
	Triggers    []string
	Handler     func(event *irc.Event, callback func(*ReplyCallbackData)) bool
}

// NewBot creates a new Bot, sets the required parameters and open the connection to the server.
func NewBot(nick, server, channel, channelKey string) *Bot {
	bot := Bot{nick: nick, server: server, channel: channel, channelKey: channelKey, Admins: new([]string)}

	bot.ircConn = irc.IRC(nick, nick)
	bot.ircConn.UseTLS = true
	bot.ircConn.Connect(server)

	//PRIVMSG
	bot.ircConn.AddCallback("PRIVMSG", bot.mainHandler)

	// RPL_WELCOME
	bot.ircConn.AddCallback("001", func(event *irc.Event) {
		bot.ircConn.Join(channel + " " + channelKey)
		// Necessary because the callback for RPL_NAMREPLY is called after joining the channel (NAMES command)
		// If not called here updateAdminsDone will always contains a value before being read by UpdateAdministrators()
		<-updateAdminsDone
	})

	// RPL_NAMREPLY
	bot.ircConn.AddCallback("353", func(event *irc.Event) {
		var currentAdmins []string
		for _, user := range strings.Split(event.Message(), " ") {
			if strings.HasPrefix(user, "@") {
				currentAdmins = append(currentAdmins, strings.TrimPrefix(user, "@"))
			}
		}
		*bot.Admins = currentAdmins
		log.Printf("Current admnistrators: %s", strings.Join(currentAdmins, ", "))
		updateAdminsDone <- true
	})

	bot.cmdHandlers = make(map[string]func(*irc.Event, func(*ReplyCallbackData)) bool)
	bot.cmdReplyCallbacks = make(map[string]func(*ReplyCallbackData))
	return &bot
}

// AddMsgHandler adds a message handler to bot.
// msgProcessCallback will be called on every user message the bot reads (if a command was not found previously in the message).
// replyCallback is to be called by msgProcessCallback (or not) to yield and process its result as a string message.
func (bot *Bot) AddMsgHandler(msgProcessCallback func(*irc.Event, func(*ReplyCallbackData)), replyCallback func(*ReplyCallbackData)) {
	if msgProcessCallback != nil {
		bot.msgHandlers = append(bot.msgHandlers, msgProcessCallback)
		bot.msgReplyCallbacks = append(bot.msgReplyCallbacks, replyCallback)
	}
}

// AddCmdHandler adds a command handler to bot.
// cmdStruct is a pointer to a Command structure.
// replyCallback is to be called by cmdProcessCallback (or not) to yield and process its result as a string message.
// Command handlers must return true if they found a command to process, false otherwise
func (bot *Bot) AddCmdHandler(cmdStruct *Command, replyCallback func(*ReplyCallbackData)) {
	if cmdStruct.Handler == nil {
		return
	}
	for _, command := range cmdStruct.Triggers {
		bot.cmdHandlers[command] = cmdStruct.Handler
		bot.cmdReplyCallbacks[command] = replyCallback
	}
}

// Run starts the event loop
func (bot *Bot) Run() {
	bot.ircConn.Loop()
}

// Stop exits the event loop
func (bot *Bot) Stop() {
	// Quit the current connection and disconnect from the server (details: https://tools.ietf.org/html/rfc1459#section-4.1.6)
	bot.ircConn.Quit()
}

// ReplyToAll sends a message to the channel where the bot is connected
func (bot *Bot) ReplyToAll(data *ReplyCallbackData) {
	bot.ircConn.Privmsg(bot.channel, data.Message)
}

// Reply sends a message to the user or channel specifed by "data.Target".
func (bot *Bot) Reply(data *ReplyCallbackData) {
	if data.Target != "" {
		bot.ircConn.Privmsg(data.Target, data.Message)
	}
}

// mainHandler is called on every message posted in the channel where the bot is connected or directly sent to the bot.
func (bot *Bot) mainHandler(event *irc.Event) {

	cmd := strings.Fields(event.Message())[0]
	cmdHandler, present := bot.cmdHandlers[cmd]
	if present {
		go cmdHandler(event, bot.cmdReplyCallbacks[cmd])
		return
	}

	for i, handler := range bot.msgHandlers {
		go handler(event, bot.msgReplyCallbacks[i])
	}
}

func UpdateAdministrators(event *irc.Event) {
	event.Connection.SendRawf("NAMES %s", event.Arguments[0])
	<-updateAdminsDone
}

func GetTargetFromEvent(event *irc.Event) string {
	source := strings.TrimSpace(event.Arguments[0])
	if strings.HasPrefix(source, "#") {
		return source
	} else {
		return event.Nick
	}
}
<commit_msg>Fix lock problem following modifications on go-ircevent<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Romain LÉTENDART
//
// See LICENSE file.

// Package core contains the bot's core functionalities
package core

import (
	"github.com/thoj/go-ircevent"
	"log"
	"strings"
)

var (
	updateAdminsDone = make(chan bool, 1)
)

// Bot structure that contains connection informations, IRC connection, command handlers and message handlers
type Bot struct {
	nick              string
	server            string
	channel           string
	channelKey        string
	Admins            *[]string
	ircConn           *irc.Connection
	msgHandlers       []func(*irc.Event, func(*ReplyCallbackData))
	msgReplyCallbacks []func(*ReplyCallbackData)
	cmdHandlers       map[string]func(*irc.Event, func(*ReplyCallbackData)) bool
	cmdReplyCallbacks map[string]func(*ReplyCallbackData)
}

// ReplyCallbackData Structure used by the handlers to send data in a standardized format
type ReplyCallbackData struct {
	Message string // Message to send
	Target  string // Destination target of the message (Channel or Nick)
}

// Command structure
type Command struct {
	Module      string
	HelpMessage string
	Triggers    []string
	Handler     func(event *irc.Event, callback func(*ReplyCallbackData)) bool
}

// NewBot creates a new Bot, sets the required parameters and open the connection to the server.
func NewBot(nick, server, channel, channelKey string) *Bot {
	bot := Bot{nick: nick, server: server, channel: channel, channelKey: channelKey, Admins: new([]string)}

	bot.ircConn = irc.IRC(nick, nick)
	bot.ircConn.UseTLS = true
	bot.ircConn.Connect(server)

	//PRIVMSG
	bot.ircConn.AddCallback("PRIVMSG", bot.mainHandler)

	// RPL_WELCOME
	bot.ircConn.AddCallback("001", func(event *irc.Event) {
		go func(event *irc.Event) {
			bot.ircConn.Join(channel + " " + channelKey)
			// Necessary because the callback for RPL_NAMREPLY is called after joining the channel (NAMES command)
			// If not called here updateAdminsDone will always contains a value before being read by UpdateAdministrators()
			<-updateAdminsDone
		}(event)
	})

	// RPL_NAMREPLY
	bot.ircConn.AddCallback("353", func(event *irc.Event) {
		var currentAdmins []string
		for _, user := range strings.Split(event.Message(), " ") {
			if strings.HasPrefix(user, "@") {
				currentAdmins = append(currentAdmins, strings.TrimPrefix(user, "@"))
			}
		}
		*bot.Admins = currentAdmins
		log.Printf("Current admnistrators: %s", strings.Join(currentAdmins, ", "))
		updateAdminsDone <- true
	})

	bot.cmdHandlers = make(map[string]func(*irc.Event, func(*ReplyCallbackData)) bool)
	bot.cmdReplyCallbacks = make(map[string]func(*ReplyCallbackData))
	return &bot
}

// AddMsgHandler adds a message handler to bot.
// msgProcessCallback will be called on every user message the bot reads (if a command was not found previously in the message).
// replyCallback is to be called by msgProcessCallback (or not) to yield and process its result as a string message.
func (bot *Bot) AddMsgHandler(msgProcessCallback func(*irc.Event, func(*ReplyCallbackData)), replyCallback func(*ReplyCallbackData)) {
	if msgProcessCallback != nil {
		bot.msgHandlers = append(bot.msgHandlers, msgProcessCallback)
		bot.msgReplyCallbacks = append(bot.msgReplyCallbacks, replyCallback)
	}
}

// AddCmdHandler adds a command handler to bot.
// cmdStruct is a pointer to a Command structure.
// replyCallback is to be called by cmdProcessCallback (or not) to yield and process its result as a string message.
// Command handlers must return true if they found a command to process, false otherwise
func (bot *Bot) AddCmdHandler(cmdStruct *Command, replyCallback func(*ReplyCallbackData)) {
	if cmdStruct.Handler == nil {
		return
	}
	for _, command := range cmdStruct.Triggers {
		bot.cmdHandlers[command] = cmdStruct.Handler
		bot.cmdReplyCallbacks[command] = replyCallback
	}
}

// Run starts the event loop
func (bot *Bot) Run() {
	bot.ircConn.Loop()
}

// Stop exits the event loop
func (bot *Bot) Stop() {
	// Quit the current connection and disconnect from the server (details: https://tools.ietf.org/html/rfc1459#section-4.1.6)
	bot.ircConn.Quit()
}

// ReplyToAll sends a message to the channel where the bot is connected
func (bot *Bot) ReplyToAll(data *ReplyCallbackData) {
	bot.ircConn.Privmsg(bot.channel, data.Message)
}

// Reply sends a message to the user or channel specifed by "data.Target".
func (bot *Bot) Reply(data *ReplyCallbackData) {
	if data.Target != "" {
		bot.ircConn.Privmsg(data.Target, data.Message)
	}
}

// mainHandler is called on every message posted in the channel where the bot is connected or directly sent to the bot.
func (bot *Bot) mainHandler(event *irc.Event) {

	cmd := strings.Fields(event.Message())[0]
	cmdHandler, present := bot.cmdHandlers[cmd]
	if present {
		go cmdHandler(event, bot.cmdReplyCallbacks[cmd])
		return
	}

	for i, handler := range bot.msgHandlers {
		go handler(event, bot.msgReplyCallbacks[i])
	}
}

func UpdateAdministrators(event *irc.Event) {
	event.Connection.SendRawf("NAMES %s", event.Arguments[0])
	<-updateAdminsDone
}

func GetTargetFromEvent(event *irc.Event) string {
	source := strings.TrimSpace(event.Arguments[0])
	if strings.HasPrefix(source, "#") {
		return source
	} else {
		return event.Nick
	}
}
<|endoftext|>


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

// genlocal is a binary for generating gapics locally. It may be used to test out
// new changes, test the generation of a new library, test new generator tweaks,
// run generators against googleapis-private, and various other local tasks.
package main

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"cloud.google.com/go/internal/gapicgen"
	"cloud.google.com/go/internal/gapicgen/generator"
	"golang.org/x/sync/errgroup"
	"gopkg.in/src-d/go-git.v4"
)

var (
	toolsNeeded = []string{"go", "protoc"}

	usage = func() {
		fmt.Fprintln(os.Stderr, "genlocal")
		os.Exit(2)
	}
)

func main() {
	log.SetFlags(0)

	flag.Usage = usage
	flag.Parse()

	ctx := context.Background()

	if err := gapicgen.VerifyAllToolsExist(toolsNeeded); err != nil {
		log.Fatal(err)
	}

	// Create temp dirs.

	log.Println("creating temp dir")
	tmpDir, err := ioutil.TempDir("", "update-genproto")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("working out %s\n", tmpDir)

	googleapisDir := filepath.Join(tmpDir, "googleapis")
	gocloudDir := filepath.Join(tmpDir, "gocloud")
	genprotoDir := filepath.Join(tmpDir, "genproto")
	protoDir := filepath.Join(tmpDir, "proto")

	// Clone repos.

	grp, _ := errgroup.WithContext(ctx)
	grp.Go(func() error {
		return gitClone("https://github.com/googleapis/googleapis.git", googleapisDir)
	})
	grp.Go(func() error {
		return gitClone("https://github.com/googleapis/go-genproto", genprotoDir)
	})
	grp.Go(func() error {
		return gitClone("https://code.googlesource.com/gocloud", gocloudDir)
	})
	grp.Go(func() error {
		return gitClone("https://github.com/google/protobuf", protoDir)
	})
	if err := grp.Wait(); err != nil {
		log.Println(err)
	}

	// Regen.

	if err := generator.Generate(ctx, googleapisDir, genprotoDir, gocloudDir, protoDir); err != nil {
		log.Printf("Generator ran (and failed) in %s\n", tmpDir)
		log.Fatal(err)
	}

	// Log results.

	log.Println(genprotoDir)
	log.Println(gocloudDir)
}

// gitClone clones a repository in the given directory.
func gitClone(repo, dir string) error {
	log.Printf("cloning %s\n", repo)

	_, err := git.PlainClone(dir, false, &git.CloneOptions{
		URL:      repo,
		Progress: os.Stdout,
	})
	return err
}
<commit_msg>internal/gapicgen: provide flags for using local code caches<commit_after>// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// genlocal is a binary for generating gapics locally. It may be used to test out
// new changes, test the generation of a new library, test new generator tweaks,
// run generators against googleapis-private, and various other local tasks.
package main

import (
	"context"
	"flag"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	"cloud.google.com/go/internal/gapicgen"
	"cloud.google.com/go/internal/gapicgen/generator"
	"golang.org/x/sync/errgroup"
	"gopkg.in/src-d/go-git.v4"
)

var (
	toolsNeeded = []string{"go", "protoc"}
)

func main() {
	log.SetFlags(0)
	if err := gapicgen.VerifyAllToolsExist(toolsNeeded); err != nil {
		log.Fatal(err)
	}

	log.Println("creating temp dir")
	tmpDir, err := ioutil.TempDir("", "update-genproto")
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("temp dir created at %s\n", tmpDir)

	googleapisDir := flag.String("googleapis-dir", filepath.Join(tmpDir, "googleapis"), "Directory where sources of googleapis/googleapis resides. If unset the sources will be cloned to a temporary directory that is not cleaned up.")
	gocloudDir := flag.String("gocloud-dir", filepath.Join(tmpDir, "gocloud"), "Directory where sources of googleapis/google-cloud-go resides. If unset the sources will be cloned to a temporary directory that is not cleaned up.")
	genprotoDir := flag.String("genproto-dir", filepath.Join(tmpDir, "genproto"), "Directory where sources of googleapis/go-genproto resides. If unset the sources will be cloned to a temporary directory that is not cleaned up.")
	protoDir := flag.String("proto-dir", filepath.Join(tmpDir, "proto"), "Directory where sources of google/protobuf resides. If unset the sources will be cloned to a temporary directory that is not cleaned up.")
	flag.Parse()

	ctx := context.Background()

	// Clone repositories if needed.

	grp, _ := errgroup.WithContext(ctx)
	gitClone(grp, "https://github.com/googleapis/googleapis.git", *googleapisDir, tmpDir)
	gitClone(grp, "https://github.com/googleapis/go-genproto", *genprotoDir, tmpDir)
	gitClone(grp, "https://code.googlesource.com/gocloud", *gocloudDir, tmpDir)
	gitClone(grp, "https://github.com/google/protobuf", *protoDir, tmpDir)
	if err := grp.Wait(); err != nil {
		log.Println(err)
	}

	// Regen.

	if err := generator.Generate(ctx, *googleapisDir, *genprotoDir, *gocloudDir, *protoDir); err != nil {
		log.Printf("Generator ran (and failed) in %s\n", tmpDir)
		log.Fatal(err)
	}

	// Log results.

	log.Println(genprotoDir)
	log.Println(gocloudDir)
}

// gitClone clones a repository in the given directory if dir is not in tmpDir.
func gitClone(eg *errgroup.Group, repo, dir, tmpDir string) {
	if !strings.HasPrefix(dir, tmpDir) {
		return
	}
	eg.Go(func() error {
		log.Printf("cloning %s\n", repo)

		_, err := git.PlainClone(dir, false, &git.CloneOptions{
			URL:      repo,
			Progress: os.Stdout,
		})
		return err
	})
}
<|endoftext|>


<commit_before>package terraform

import (
	"log"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/dag"
	"github.com/hashicorp/terraform/internal/plans"
)

// OutputTransformer is a GraphTransformer that adds all the outputs
// in the configuration to the graph.
//
// This is done for the apply graph builder even if dependent nodes
// aren't changing since there is no downside: the state will be available
// even if the dependent items aren't changing.
type OutputTransformer struct {
	Config  *configs.Config
	Changes *plans.Changes

	// If this is a planned destroy, root outputs are still in the configuration
	// so we need to record that we wish to remove them
	Destroy bool

	// Refresh-only mode means that any failing output preconditions are
	// reported as warnings rather than errors
	RefreshOnly bool
}

func (t *OutputTransformer) Transform(g *Graph) error {
	return t.transform(g, t.Config)
}

func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error {
	// If we have no config then there can be no outputs.
	if c == nil {
		return nil
	}

	// Transform all the children. We must do this first because
	// we can reference module outputs and they must show up in the
	// reference map.
	for _, cc := range c.Children {
		if err := t.transform(g, cc); err != nil {
			return err
		}
	}

	// Add outputs to the graph, which will be dynamically expanded
	// into NodeApplyableOutputs to reflect possible expansion
	// through the presence of "count" or "for_each" on the modules.

	var changes []*plans.OutputChangeSrc
	if t.Changes != nil {
		changes = t.Changes.Outputs
	}

	for _, o := range c.Module.Outputs {
		addr := addrs.OutputValue{Name: o.Name}

		var rootChange *plans.OutputChangeSrc
		for _, c := range changes {
			if c.Addr.Module.IsRoot() && c.Addr.OutputValue.Name == o.Name {
				rootChange = c
			}
		}

		destroy := t.Destroy
		if rootChange != nil {
			destroy = rootChange.Action == plans.Delete
		}

		// If this is a root output, we add the apply or destroy node directly,
		// as the root modules does not expand.

		var node dag.Vertex
		switch {
		case c.Path.IsRoot() && destroy:
			node = &NodeDestroyableOutput{
				Addr:   addr.Absolute(addrs.RootModuleInstance),
				Config: o,
			}

		case c.Path.IsRoot():
			node = &NodeApplyableOutput{
				Addr:        addr.Absolute(addrs.RootModuleInstance),
				Config:      o,
				Change:      rootChange,
				RefreshOnly: t.RefreshOnly,
			}

		default:
			node = &nodeExpandOutput{
				Addr:        addr,
				Module:      c.Path,
				Config:      o,
				Destroy:     t.Destroy,
				RefreshOnly: t.RefreshOnly,
			}
		}

		log.Printf("[TRACE] OutputTransformer: adding %s as %T", o.Name, node)
		g.Add(node)
	}

	return nil
}
<commit_msg>rename field to destroyPlan for consistency<commit_after>package terraform

import (
	"log"

	"github.com/hashicorp/terraform/internal/addrs"
	"github.com/hashicorp/terraform/internal/configs"
	"github.com/hashicorp/terraform/internal/dag"
	"github.com/hashicorp/terraform/internal/plans"
)

// OutputTransformer is a GraphTransformer that adds all the outputs
// in the configuration to the graph.
//
// This is done for the apply graph builder even if dependent nodes
// aren't changing since there is no downside: the state will be available
// even if the dependent items aren't changing.
type OutputTransformer struct {
	Config  *configs.Config
	Changes *plans.Changes

	// If this is a planned destroy, root outputs are still in the configuration
	// so we need to record that we wish to remove them
	destroyPlan bool

	// Refresh-only mode means that any failing output preconditions are
	// reported as warnings rather than errors
	RefreshOnly bool
}

func (t *OutputTransformer) Transform(g *Graph) error {
	return t.transform(g, t.Config)
}

func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error {
	// If we have no config then there can be no outputs.
	if c == nil {
		return nil
	}

	// Transform all the children. We must do this first because
	// we can reference module outputs and they must show up in the
	// reference map.
	for _, cc := range c.Children {
		if err := t.transform(g, cc); err != nil {
			return err
		}
	}

	// Add outputs to the graph, which will be dynamically expanded
	// into NodeApplyableOutputs to reflect possible expansion
	// through the presence of "count" or "for_each" on the modules.

	var changes []*plans.OutputChangeSrc
	if t.Changes != nil {
		changes = t.Changes.Outputs
	}

	for _, o := range c.Module.Outputs {
		addr := addrs.OutputValue{Name: o.Name}

		var rootChange *plans.OutputChangeSrc
		for _, c := range changes {
			if c.Addr.Module.IsRoot() && c.Addr.OutputValue.Name == o.Name {
				rootChange = c
			}
		}

		destroy := t.destroyPlan
		if rootChange != nil {
			destroy = rootChange.Action == plans.Delete
		}

		// If this is a root output, we add the apply or destroy node directly,
		// as the root modules does not expand.

		var node dag.Vertex
		switch {
		case c.Path.IsRoot() && destroy:
			node = &NodeDestroyableOutput{
				Addr:   addr.Absolute(addrs.RootModuleInstance),
				Config: o,
			}

		case c.Path.IsRoot():
			node = &NodeApplyableOutput{
				Addr:        addr.Absolute(addrs.RootModuleInstance),
				Config:      o,
				Change:      rootChange,
				RefreshOnly: t.RefreshOnly,
			}

		default:
			node = &nodeExpandOutput{
				Addr:        addr,
				Module:      c.Path,
				Config:      o,
				Destroy:     t.destroyPlan,
				RefreshOnly: t.RefreshOnly,
			}
		}

		log.Printf("[TRACE] OutputTransformer: adding %s as %T", o.Name, node)
		g.Add(node)
	}

	return nil
}
<|endoftext|>