<commit_before>package sources

import (
	"time"

	"github.com/OWASP/Amass/services"
	"github.com/OWASP/Amass/config"
	eb "github.com/OWASP/Amass/eventbus"
	"github.com/OWASP/Amass/resolvers"
	"github.com/OWASP/Amass/requests"
)

// Pastebin is the Service that handles access to the CertSpotter data source.
type Pastebin struct {
	services.BaseService

	SourceType string
	RateLimit  time.Duration
}

// NewPastebin returns he object initialized, but not yet started.
func NewPastebin(cfg *config.Config, bus *eb.EventBus, pool *resolvers.ResolverPool) *Pastebin {
	p := &Pastebin{
		SourceType: requests.API,
		RateLimit:  3 * time.Second,
	}

	p.BaseService = *services.NewBaseService(p, "Pastebin", cfg, bus, pool)
	return p
}

// OnStart implements the Service interface
func (p *Pastebin) OnStart() error {
	p.BaseService.OnStart()

	go p.processRequests()
	return nil
}

func (p *Pastebin) processRequests() {
	last := time.Now()

	for {
		select {
		case <-p.Quit():
			return
		case req := <-p.DNSRequestChan():
			if p.Config().IsDomainInScope(req.Domain) {
				if time.Now().Sub(last) < p.RateLimit {
					time.Sleep(p.RateLimit)
				}
				last = time.Now()
				p.executeQuery(req.Domain)
				last = time.Now()
			}
		case <-p.AddrRequestChan():
		case <-p.ASNRequestChan():
		case <-p.WhoisRequestChan():
		}
	}
}

func (p *Pastebin) executeQuery(domain string) {

}<commit_msg>Update: Created the webURLDumpIDs method in pastebin.go that provides the Web url to fetch dump ids<commit_after>package sources

import (
	"time"
	"fmt"

	"github.com/OWASP/Amass/services"
	"github.com/OWASP/Amass/config"
	eb "github.com/OWASP/Amass/eventbus"
	"github.com/OWASP/Amass/resolvers"
	"github.com/OWASP/Amass/requests"
	"github.com/davecgh/go-spew/spew"
)

// Pastebin is the Service that handles access to the CertSpotter data source.
type Pastebin struct {
	services.BaseService

	SourceType string
	RateLimit  time.Duration
}

// NewPastebin returns he object initialized, but not yet started.
func NewPastebin(cfg *config.Config, bus *eb.EventBus, pool *resolvers.ResolverPool) *Pastebin {
	p := &Pastebin{
		SourceType: requests.API,
		RateLimit:  3 * time.Second,
	}

	p.BaseService = *services.NewBaseService(p, "Pastebin", cfg, bus, pool)
	return p
}

// OnStart implements the Service interface
func (p *Pastebin) OnStart() error {
	p.BaseService.OnStart()

	go p.processRequests()
	return nil
}

func (p *Pastebin) processRequests() {
	last := time.Now()

	for {
		select {
		case <-p.Quit():
			return
		case req := <-p.DNSRequestChan():
			if p.Config().IsDomainInScope(req.Domain) {
				if time.Now().Sub(last) < p.RateLimit {
					time.Sleep(p.RateLimit)
				}
				last = time.Now()
				p.executeQuery(req.Domain)
				last = time.Now()
			}
		case <-p.AddrRequestChan():
		case <-p.ASNRequestChan():
		case <-p.WhoisRequestChan():
		}
	}
}

func (p *Pastebin) executeQuery(domain string) {
	re := p.Config().DomainRegex(domain)
	spew.Dump(re)
	spew.Dump(p.webURLDumpIDs(domain))

}

// Returns the Web URL to fetch all dump ids for a given doamin
func (p *Pastebin) webURLDumpIDs(domain string) string {
	return fmt.Sprintf("https://psbdmp.ws/api/search/%s", domain)
}<|endoftext|>


<commit_before>// Copyright 2016, RadiantBlue Technologies, 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,
// 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 logger

import (
	"log"
	"strconv"
	"sync"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	"github.com/venicegeo/pz-gocommon/syslog"
)

//---------------------------------------------------------------------

const schemaMappingX = `{
	"dynamic": "strict",
	"properties": {
		"facility": {
			"type": "int"
		},
		"severity": {
			"type": "int"
		},
		"version": {
			"type": "int"
		},
		"timeStamp": {
			"type": "date"
		},
		"hostName": {
			"type": "string"
		},
		"application": {
			"type": "string"
		},
		"process": {
			"type": "string"
		},
		"messageId": {
			"type": "string"
		},
		"message": {
			"type": "string"
		}
	}
}`

const schemaMapping = `{
	"dynamic": "strict",
	"properties": {
		"service": {
				"type": "string",
				"store": true,
				"index": "not_analyzed"
		},
		"address": {
				"type": "string",
				"store": true,
				"index": "not_analyzed"
		},
		"createdOn": {
				"type": "date",
				"store": true,
				"index": "not_analyzed"
		},
		"severity": {
				"type": "string",
				"store": true,
				"index": "not_analyzed"
		},
		"message": {
				"type": "string",
				"store": true,
				"index": "analyzed"
		}
	}
}`

const logSchema = "LogData7x"
const auditSchema = "AuditData7x"
const logSchemaMapping = "{\"LogData7x\": " + schemaMapping + " }"
const auditSchemaMapping = "{\"AuditData7x\": " + schemaMapping + " }"

type ElasticsearchWriter struct {
	sync.Mutex
	id      int
	esIndex elasticsearch.IIndex
}

func NewElasticsearchWriter(esIndex elasticsearch.IIndex) (*ElasticsearchWriter, error) {
	w := &ElasticsearchWriter{
		esIndex: esIndex,
	}

	err := setupIndex(esIndex)
	if err != nil {
		return nil, err
	}

	return w, nil
}

// Write writes the message to the supplied file.
func (w *ElasticsearchWriter) Write(mssg *syslog.Message) error {
	var err error

	err = mssg.Validate()
	if err != nil {
		return err
	}

	mssgOld, err := convertNewMessageToOld(mssg)
	if err != nil {
		return err
	}

	w.Lock()
	idStr := strconv.Itoa(w.id)
	w.id++
	w.Unlock()

	_, err = w.esIndex.PostData(logSchema, idStr, mssgOld)
	if err != nil {
		log.Printf("old message post: %s", err.Error())
		// don't return yet, the audit post might still work
	}

	if mssg.AuditData != nil {
		_, err = w.esIndex.PostData(auditSchema, idStr, mssgOld)
		if err != nil {
			log.Printf("old message audit post: %s", err.Error())
		}
	}

	return nil
}

//---------------------------------------------------------------------

func setupIndex(esIndex elasticsearch.IIndex) error {
	err := createIndex(esIndex)
	if err != nil {
		return err
	}

	log.Printf("%s", logSchema)
	log.Printf("%s", logSchemaMapping)
	err = createType(esIndex, logSchema, logSchemaMapping)
	if err != nil {
		return err
	}
	err = createType(esIndex, auditSchema, auditSchemaMapping)
	return err
}

func createIndex(esIndex elasticsearch.IIndex) error {
	ok, err := esIndex.IndexExists()
	if err != nil {
		return err
	}
	if ok {
		return nil
	}

	log.Printf("Creating index: %s", esIndex.IndexName())
	err = esIndex.Create("")
	return err
}

func createType(
	esIndex elasticsearch.IIndex,
	schema string,
	mapping string) error {

	ok, err := esIndex.TypeExists(schema)
	if err != nil {
		return err
	}
	if ok {
		return nil
	}

	log.Printf("Creating type: %s", schema)
	err = esIndex.SetMapping(schema, piazza.JsonString(mapping))
	return err
}
<commit_msg>Revert "debugging"<commit_after>// Copyright 2016, RadiantBlue Technologies, 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,
// 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 logger

import (
	"log"
	"strconv"
	"sync"

	"github.com/venicegeo/pz-gocommon/elasticsearch"
	piazza "github.com/venicegeo/pz-gocommon/gocommon"
	"github.com/venicegeo/pz-gocommon/syslog"
)

//---------------------------------------------------------------------

const schemaMappingX = `{
	"dynamic": "strict",
	"properties": {
		"facility": {
			"type": "int"
		},
		"severity": {
			"type": "int"
		},
		"version": {
			"type": "int"
		},
		"timeStamp": {
			"type": "date"
		},
		"hostName": {
			"type": "string"
		},
		"application": {
			"type": "string"
		},
		"process": {
			"type": "string"
		},
		"messageId": {
			"type": "string"
		},
		"message": {
			"type": "string"
		}
	}
}`

const schemaMapping = `{
	"dynamic": "strict",
	"properties": {
		"service": {
				"type": "string",
				"store": true,
				"index": "not_analyzed"
		},
		"address": {
				"type": "string",
				"store": true,
				"index": "not_analyzed"
		},
		"createdOn": {
				"type": "date",
				"store": true,
				"index": "not_analyzed"
		},
		"severity": {
				"type": "string",
				"store": true,
				"index": "not_analyzed"
		},
		"message": {
				"type": "string",
				"store": true,
				"index": "analyzed"
		}
	}
}`

const logSchema = "LogData7x"
const auditSchema = "AuditData7x"
const logSchemaMapping = "{\"LogData7\": " + schemaMapping + " }"
const auditSchemaMapping = "{\"AuditData7\": " + schemaMapping + " }"

type ElasticsearchWriter struct {
	sync.Mutex
	id      int
	esIndex elasticsearch.IIndex
}

func NewElasticsearchWriter(esIndex elasticsearch.IIndex) (*ElasticsearchWriter, error) {
	w := &ElasticsearchWriter{
		esIndex: esIndex,
	}

	err := setupIndex(esIndex)
	if err != nil {
		return nil, err
	}

	return w, nil
}

// Write writes the message to the supplied file.
func (w *ElasticsearchWriter) Write(mssg *syslog.Message) error {
	var err error

	err = mssg.Validate()
	if err != nil {
		return err
	}

	mssgOld, err := convertNewMessageToOld(mssg)
	if err != nil {
		return err
	}

	w.Lock()
	idStr := strconv.Itoa(w.id)
	w.id++
	w.Unlock()

	_, err = w.esIndex.PostData(logSchema, idStr, mssgOld)
	if err != nil {
		log.Printf("old message post: %s", err.Error())
		// don't return yet, the audit post might still work
	}

	if mssg.AuditData != nil {
		_, err = w.esIndex.PostData(auditSchema, idStr, mssgOld)
		if err != nil {
			log.Printf("old message audit post: %s", err.Error())
		}
	}

	return nil
}

//---------------------------------------------------------------------

func setupIndex(esIndex elasticsearch.IIndex) error {
	err := createIndex(esIndex)
	if err != nil {
		return err
	}
	err = createType(esIndex, logSchema, logSchemaMapping)
	if err != nil {
		return err
	}
	err = createType(esIndex, auditSchema, auditSchemaMapping)
	return err
}

func createIndex(esIndex elasticsearch.IIndex) error {
	ok, err := esIndex.IndexExists()
	if err != nil {
		return err
	}
	if ok {
		return nil
	}

	log.Printf("Creating index: %s", esIndex.IndexName())
	err = esIndex.Create("")
	return err
}

func createType(
	esIndex elasticsearch.IIndex,
	schema string,
	mapping string) error {

	ok, err := esIndex.TypeExists(schema)
	if err != nil {
		return err
	}
	if ok {
		return nil
	}

	log.Printf("Creating type: %s", schema)
	err = esIndex.SetMapping(schema, piazza.JsonString(mapping))
	return err
}
<|endoftext|>


<commit_before>package router

import (
	"errors"
	"sync"
	"time"

	"github.com/google/uuid"
)

var (
	// ErrRouteNotFound is returned when no route was found in the routing table
	ErrRouteNotFound = errors.New("route not found")
	// ErrDuplicateRoute is returned when the route already exists
	ErrDuplicateRoute = errors.New("duplicate route")
)

// table is an in memory routing table
type table struct {
	sync.RWMutex
	// routes stores service routes
	routes map[string]map[uint64]Route
	// watchers stores table watchers
	watchers map[string]*tableWatcher
}

// newtable creates a new routing table and returns it
func newTable(opts ...Option) *table {
	return &table{
		routes:   make(map[string]map[uint64]Route),
		watchers: make(map[string]*tableWatcher),
	}
}

// Create creates new route in the routing table
func (t *table) Create(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if there are any routes in the table for the route destination
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	// add new route to the table for the route destination
	if _, ok := t.routes[service][sum]; !ok {
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	return ErrDuplicateRoute
}

// Delete deletes the route from the routing table
func (t *table) Delete(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	if _, ok := t.routes[service]; !ok {
		return ErrRouteNotFound
	}

	delete(t.routes[service], sum)
	go t.sendEvent(&Event{Type: Delete, Timestamp: time.Now(), Route: r})

	return nil
}

// Update updates routing table with the new route
func (t *table) Update(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if the route destination has any routes in the table
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	t.routes[service][sum] = r
	go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r})

	return nil
}

// List returns a list of all routes in the table
func (t *table) List() ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	var routes []Route
	for _, rmap := range t.routes {
		for _, route := range rmap {
			routes = append(routes, route)
		}
	}

	return routes, nil
}

// isMatch checks if the route matches given network and router
func isMatch(route Route, network, router string) bool {
	if network == "*" || network == route.Network {
		if router == "*" || router == route.Gateway {
			return true
		}
	}
	return false
}

// findRoutes finds all the routes for given network and router and returns them
func findRoutes(routes map[uint64]Route, network, router string) []Route {
	var results []Route
	for _, route := range routes {
		if isMatch(route, network, router) {
			results = append(results, route)
		}
	}
	return results
}

// Lookup queries routing table and returns all routes that match the lookup query
func (t *table) Lookup(q Query) ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	if q.Options().Service != "*" {
		if _, ok := t.routes[q.Options().Service]; !ok {
			return nil, ErrRouteNotFound
		}
		return findRoutes(t.routes[q.Options().Service], q.Options().Network, q.Options().Gateway), nil
	}

	var results []Route
	// search through all destinations
	for _, routes := range t.routes {
		results = append(results, findRoutes(routes, q.Options().Network, q.Options().Gateway)...)
	}

	return results, nil
}

// Watch returns routing table entry watcher
func (t *table) Watch(opts ...WatchOption) (Watcher, error) {
	// by default watch everything
	wopts := WatchOptions{
		Service: "*",
	}

	for _, o := range opts {
		o(&wopts)
	}

	w := &tableWatcher{
		opts:    wopts,
		resChan: make(chan *Event, 10),
		done:    make(chan struct{}),
	}

	t.Lock()
	t.watchers[uuid.New().String()] = w
	t.Unlock()

	return w, nil
}

// sendEvent sends events to all subscribed watchers
func (t *table) sendEvent(e *Event) {
	t.RLock()
	defer t.RUnlock()

	for _, w := range t.watchers {
		select {
		case w.resChan <- e:
		case <-w.done:
		}
	}
}
<commit_msg>syntactic changes<commit_after>package router

import (
	"errors"
	"sync"
	"time"

	"github.com/google/uuid"
)

// table is an in memory routing table
type table struct {
	sync.RWMutex
	// routes stores service routes
	routes map[string]map[uint64]Route
	// watchers stores table watchers
	watchers map[string]*tableWatcher
}

// newtable creates a new routing table and returns it
func newTable(opts ...Option) *table {
	return &table{
		routes:   make(map[string]map[uint64]Route),
		watchers: make(map[string]*tableWatcher),
	}
}

// Create creates new route in the routing table
func (t *table) Create(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if there are any routes in the table for the route destination
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	// add new route to the table for the route destination
	if _, ok := t.routes[service][sum]; !ok {
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	return ErrDuplicateRoute
}

// Delete deletes the route from the routing table
func (t *table) Delete(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	if _, ok := t.routes[service]; !ok {
		return ErrRouteNotFound
	}

	delete(t.routes[service], sum)
	go t.sendEvent(&Event{Type: Delete, Timestamp: time.Now(), Route: r})

	return nil
}

// Update updates routing table with the new route
func (t *table) Update(r Route) error {
	service := r.Service
	sum := r.Hash()

	t.Lock()
	defer t.Unlock()

	// check if the route destination has any routes in the table
	if _, ok := t.routes[service]; !ok {
		t.routes[service] = make(map[uint64]Route)
		t.routes[service][sum] = r
		go t.sendEvent(&Event{Type: Create, Timestamp: time.Now(), Route: r})
		return nil
	}

	t.routes[service][sum] = r
	go t.sendEvent(&Event{Type: Update, Timestamp: time.Now(), Route: r})

	return nil
}

// List returns a list of all routes in the table
func (t *table) List() ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	var routes []Route
	for _, rmap := range t.routes {
		for _, route := range rmap {
			routes = append(routes, route)
		}
	}

	return routes, nil
}

// isMatch checks if the route matches given network and router
func isMatch(route Route, network, router string) bool {
	if network == "*" || network == route.Network {
		if router == "*" || router == route.Gateway {
			return true
		}
	}
	return false
}

// findRoutes finds all the routes for given network and router and returns them
func findRoutes(routes map[uint64]Route, network, router string) []Route {
	var results []Route
	for _, route := range routes {
		if isMatch(route, network, router) {
			results = append(results, route)
		}
	}
	return results
}

// Lookup queries routing table and returns all routes that match the lookup query
func (t *table) Lookup(q Query) ([]Route, error) {
	t.RLock()
	defer t.RUnlock()

	if q.Options().Service != "*" {
		if _, ok := t.routes[q.Options().Service]; !ok {
			return nil, ErrRouteNotFound
		}
		return findRoutes(t.routes[q.Options().Service], q.Options().Network, q.Options().Gateway), nil
	}

	var results []Route
	// search through all destinations
	for _, routes := range t.routes {
		results = append(results, findRoutes(routes, q.Options().Network, q.Options().Gateway)...)
	}

	return results, nil
}

// Watch returns routing table entry watcher
func (t *table) Watch(opts ...WatchOption) (Watcher, error) {
	// by default watch everything
	wopts := WatchOptions{
		Service: "*",
	}

	for _, o := range opts {
		o(&wopts)
	}

	w := &tableWatcher{
		opts:    wopts,
		resChan: make(chan *Event, 10),
		done:    make(chan struct{}),
	}

	t.Lock()
	t.watchers[uuid.New().String()] = w
	t.Unlock()

	return w, nil
}

// sendEvent sends events to all subscribed watchers
func (t *table) sendEvent(e *Event) {
	t.RLock()
	defer t.RUnlock()

	for _, w := range t.watchers {
		select {
		case w.resChan <- e:
		case <-w.done:
		}
	}
}

var (
	// ErrRouteNotFound is returned when no route was found in the routing table
	ErrRouteNotFound = errors.New("route not found")
	// ErrDuplicateRoute is returned when the route already exists
	ErrDuplicateRoute = errors.New("duplicate route")
)
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/danmane/abalone/go/api"
	"github.com/danmane/abalone/go/game"
)

var (
	playAgainstHuman = flag.Bool("playAgainstHuman", false, "play against human on frontend rather than AI vs AI")
	humanPort        = flag.String("humanPort", "1337", "port for javascript frontend")
	aiPort1          = flag.String("aiPort1", "3423", "port for first ai")
	aiPort2          = flag.String("aiPort2", "3424", "port for second ai (if present)")
	timelimit        = flag.Duration("timelimit", time.Second*2, "per-move time limit")
)

func main() {
	flag.Parse()
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	whiteAI := api.Player{}
	blackAI := api.Player{}
	whiteAgent := PlayerInstance{Player: whiteAI, Port: *aiPort1}
	blackAgent := PlayerInstance{Player: blackAI, Port: *aiPort2}
	start := game.Standard
	result := playAIGame(whiteAgent, blackAgent, start)
	fmt.Println(result)
	return nil
}

type PlayerInstance struct {
	Player api.Player
	Port   string
}

func toMillisecondCount(d time.Duration) int64 {
	return int64(d / 1e6)
}

func gameFromAI(port string, state *game.State) (*game.State, error) {
	mr := api.MoveRequest{
		State:      *state,
		LimitMilli: toMillisecondCount(api.DefaultMoveLimit),
	}
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(&mr); err != nil {
		return nil, err
	}
	resp, err := http.Post("http://localhost:"+port+api.MovePath, "application/json", &buf)
	if err != nil {
		return nil, err
	}
	responseGame := &game.State{}
	if err := json.NewDecoder(resp.Body).Decode(responseGame); err != nil {
		return nil, err
	}
	resp.Body.Close()
	if !state.ValidFuture(responseGame) {
		return nil, fmt.Errorf("game parsed correctly, but isn't a valid future")
	}
	return responseGame, nil
}

func playAIGame(whiteAgent, blackAgent PlayerInstance, startState game.State) api.GameResult {
	states := []game.State{startState}
	currentGame := &startState
	victory := api.NoVictory
	outcome := game.NullOutcome
	for !currentGame.GameOver() {
		var nextAI PlayerInstance
		if currentGame.NextPlayer == game.White {
			nextAI = whiteAgent
		} else {
			nextAI = blackAgent
		}
		futureGame, err := gameFromAI(nextAI.Port, currentGame)
		if err != nil {
			fmt.Println(err)
			victory = api.InvalidResponse
			outcome = currentGame.NextPlayer.Loses()
			return api.GameResult{
				White:         whiteAgent.Player,
				Black:         blackAgent.Player,
				Outcome:       outcome,
				VictoryReason: victory,
				States:        states,
			}
		}
		currentGame = futureGame
		states = append(states, *currentGame)
	}

	outcome = currentGame.Outcome()
	loser := outcome.Loser()
	if loser != game.NullPlayer && currentGame.NumPieces(loser) <= currentGame.LossThreshold {
		victory = api.StonesDepleted
	} else {
		victory = api.MovesDepleted
	}
	return api.GameResult{
		White:         whiteAgent.Player,
		Black:         blackAgent.Player,
		Outcome:       outcome,
		VictoryReason: victory,
		States:        states,
	}

}
<commit_msg>gameoperator: provide more info to console<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/danmane/abalone/go/api"
	"github.com/danmane/abalone/go/game"
)

var (
	playAgainstHuman = flag.Bool("playAgainstHuman", false, "play against human on frontend rather than AI vs AI")
	humanPort        = flag.String("humanPort", "1337", "port for javascript frontend")
	aiPort1          = flag.String("aiPort1", "3423", "port for first ai")
	aiPort2          = flag.String("aiPort2", "3424", "port for second ai (if present)")
	timelimit        = flag.Duration("timelimit", time.Second*2, "per-move time limit")
)

func main() {
	flag.Parse()
	fmt.Println("game operater operating!")
	if err := run(); err != nil {
		log.Fatal(err)
	}
}

func run() error {
	whiteAI := api.Player{}
	blackAI := api.Player{}
	whiteAgent := PlayerInstance{Player: whiteAI, Port: *aiPort1}
	blackAgent := PlayerInstance{Player: blackAI, Port: *aiPort2}
	start := game.Standard
	playAIGame(whiteAgent, blackAgent, start)
	// fmt.Println(result)
	return nil
}

type PlayerInstance struct {
	Player api.Player
	Port   string
}

func toMillisecondCount(d time.Duration) int64 {
	return int64(d / 1e6)
}

func gameFromAI(port string, state *game.State) (*game.State, error) {
	mr := api.MoveRequest{
		State:      *state,
		LimitMilli: toMillisecondCount(api.DefaultMoveLimit),
	}
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(&mr); err != nil {
		return nil, err
	}
	resp, err := http.Post("http://localhost:"+port+api.MovePath, "application/json", &buf)
	if err != nil {
		return nil, err
	}
	responseGame := &game.State{}
	if err := json.NewDecoder(resp.Body).Decode(responseGame); err != nil {
		return nil, err
	}
	resp.Body.Close()
	if !state.ValidFuture(responseGame) {
		return nil, fmt.Errorf("game parsed correctly, but isn't a valid future")
	}
	return responseGame, nil
}

func playAIGame(whiteAgent, blackAgent PlayerInstance, startState game.State) api.GameResult {
	states := []game.State{startState}
	currentGame := &startState
	victory := api.NoVictory
	outcome := game.NullOutcome
	var moves int = 0
	for !currentGame.GameOver() {
		var nextAI PlayerInstance
		fmt.Printf("move %v (%v)\n", moves, currentGame.NextPlayer.String())
		moves++
		if currentGame.NextPlayer == game.White {
			nextAI = whiteAgent
		} else {
			nextAI = blackAgent
		}
		futureGame, err := gameFromAI(nextAI.Port, currentGame)
		if err != nil {
			fmt.Println("Game is terminating due to an invalid response!")
			fmt.Println(err)
			victory = api.InvalidResponse
			outcome = currentGame.NextPlayer.Loses()
			return api.GameResult{
				White:         whiteAgent.Player,
				Black:         blackAgent.Player,
				Outcome:       outcome,
				VictoryReason: victory,
				States:        states,
			}
		}
		currentGame = futureGame
		states = append(states, *currentGame)
	}

	outcome = currentGame.Outcome()
	if outcome == game.WhiteWins {
		fmt.Printf("white wins (on port %v)\n", *aiPort1)
	} else if outcome == game.BlackWins {
		fmt.Printf("black wins (on port %v)\n", *aiPort2)
	} else {
		fmt.Println("tie game!")
	}
	loser := outcome.Loser()
	if loser != game.NullPlayer && currentGame.NumPieces(loser) <= currentGame.LossThreshold {
		fmt.Println("stones depeleted")
		victory = api.StonesDepleted
	} else {
		fmt.Println("moves depeleted")
		victory = api.MovesDepleted
	}
	return api.GameResult{
		White:         whiteAgent.Player,
		Black:         blackAgent.Player,
		Outcome:       outcome,
		VictoryReason: victory,
		States:        states,
	}

}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/eris-ltd/common/go/log" // so we can flush logs on exit/ifexit
	"github.com/mitchellh/go-homedir"
)

var (
	// Convenience Directories
	GoPath  = os.Getenv("GOPATH")
	ErisLtd = path.Join(GoPath, "src", "github.com", "eris-ltd")
	ErisGH  = "https://github.com/eris-ltd/"
	// usr, _   = user.Current() // error?!
	ErisRoot          = ResolveErisRoot()
	ErisContainerRoot = "/home/eris/.eris" // XXX: this is used as root in the `eris/base` image

	// Major Directories
	ActionsPath        = path.Join(ErisRoot, "actions")
	BlockchainsPath    = path.Join(ErisRoot, "chains")
	DataContainersPath = path.Join(ErisRoot, "data")
	AppsPath           = path.Join(ErisRoot, "apps")
	FilesPath          = path.Join(ErisRoot, "files")
	KeysPath           = path.Join(ErisRoot, "keys")
	LanguagesPath      = path.Join(ErisRoot, "languages")
	ServicesPath       = path.Join(ErisRoot, "services")
	ScratchPath        = path.Join(ErisRoot, "scratch")

	// Keys
	KeysDataPath = path.Join(KeysPath, "data")
	KeyNamesPath = path.Join(KeysPath, "names")

	// Scratch Directories (globally coordinated)
	EpmScratchPath  = path.Join(ScratchPath, "epm")
	LllcScratchPath = path.Join(ScratchPath, "lllc")
	SolcScratchPath = path.Join(ScratchPath, "sol")
	SerpScratchPath = path.Join(ScratchPath, "ser")

	// Blockchains stuff
	HEAD = path.Join(BlockchainsPath, "HEAD")
	Refs = path.Join(BlockchainsPath, "refs")
)

var MajorDirs = []string{
	ErisRoot, ActionsPath, BlockchainsPath, DataContainersPath, AppsPath, FilesPath, KeysPath, LanguagesPath, ServicesPath, KeysDataPath, KeyNamesPath, ScratchPath, EpmScratchPath, LllcScratchPath, SolcScratchPath, SerpScratchPath,
}

//---------------------------------------------
// user and process

func Usr() string {
	u, _ := homedir.Dir()
	return u
}

func Exit(err error) {
	status := 0
	if err != nil {
		log.Flush()
		fmt.Println(err)
		status = 1
	}
	os.Exit(status)
}

func IfExit(err error) {
	if err != nil {
		log.Flush()
		fmt.Println(err)
		os.Exit(1)
	}
}

// user and process
//---------------------------------------------------------------------------
// filesystem

func AbsolutePath(Datadir string, filename string) string {
	if path.IsAbs(filename) {
		return filename
	}
	return path.Join(Datadir, filename)
}

func InitDataDir(Datadir string) error {
	if _, err := os.Stat(Datadir); err != nil {
		if os.IsNotExist(err) {
			if err := os.MkdirAll(Datadir, 0777); err != nil {
				return err
			}
		}
	}
	return nil
}

func ResolveErisRoot() string {
	var eris string
	if os.Getenv("ERIS") != "" {
		eris = os.Getenv("ERIS")
	} else {
		if runtime.GOOS == "windows" {
			home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
			if home == "" {
				home = os.Getenv("USERPROFILE")
			}
			eris = path.Join(home, ".eris")
		} else {
			eris = path.Join(Usr(), ".eris")
		}
	}
	return eris
}

// Create the default eris tree
func InitErisDir() (err error) {
	for _, d := range MajorDirs {
		err := InitDataDir(d)
		if err != nil {
			return err
		}
	}
	if _, err = os.Stat(HEAD); err != nil {
		_, err = os.Create(HEAD)
	}
	return
}

func ClearDir(dir string) error {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, f := range fs {
		n := f.Name()
		if f.IsDir() {
			if err := os.RemoveAll(path.Join(dir, f.Name())); err != nil {
				return err
			}
		} else {
			if err := os.Remove(path.Join(dir, n)); err != nil {
				return err
			}
		}
	}
	return nil
}

func Copy(src, dst string) error {
	f, err := os.Stat(src)
	if err != nil {
		return err
	}
	if f.IsDir() {
		tmpDir, err := ioutil.TempDir(os.TempDir(), "eris_copy")
		if err != nil {
			return err
		}
		if err := copyDir(src, tmpDir); err != nil {
			return err
		}
		if err := copyDir(tmpDir, dst); err != nil {
			return err
		}
		// fi, err := os.Stat(src)
		// if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		// 	return err
		// }
		// return os.Rename(tmpDir, dst)
		return nil
	}
	return copyFile(src, dst)
}

// assumes we've done our checking
func copyDir(src, dst string) error {
	fi, err := os.Stat(src)
	if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		return err
	}
	fs, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}

	for _, f := range fs {
		s := path.Join(src, f.Name())
		d := path.Join(dst, f.Name())
		if f.IsDir() {
			if err := copyDir(s, d); err != nil {
				return err
			}
		} else {
			if err := copyFile(s, d); err != nil {
				return err
			}
		}
	}
	return nil
}

// common golang, really?
func copyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func WriteFile(data, path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
		return err
	}
	writer, err := os.Create(filepath.Join(path))
	defer writer.Close()
	if err != nil {
		return err
	}
	writer.Write([]byte(data))
	return nil
}

// filesystem
//-------------------------------------------------------
// open text editors

func Editor(file string) error {
	editr := os.Getenv("EDITOR")
	if strings.Contains(editr, "/") {
		editr = path.Base(editr)
	}
	switch editr {
	case "", "vim", "vi":
		return vi(file)
	case "emacs":
		return emacs(file)
	default:
		return editor(file)
	}
	// return fmt.Errorf("Unknown editor %s", editr)
}

func emacs(file string) error {
	cmd := exec.Command("emacs", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func vi(file string) error {
	cmd := exec.Command("vim", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func editor(file string) error {
	cmd := exec.Command(os.Getenv("EDITOR"), file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<commit_msg>dapps -> apps, blockchains -> chains<commit_after>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/eris-ltd/common/go/log" // so we can flush logs on exit/ifexit
	"github.com/mitchellh/go-homedir"
)

var (
	// Convenience Directories
	GoPath  = os.Getenv("GOPATH")
	ErisLtd = path.Join(GoPath, "src", "github.com", "eris-ltd")
	ErisGH  = "https://github.com/eris-ltd/"
	// usr, _   = user.Current() // error?!
	ErisRoot          = ResolveErisRoot()
	ErisContainerRoot = "/home/eris/.eris" // XXX: this is used as root in the `eris/base` image

	// Major Directories
	AppsPath           = path.Join(ErisRoot, "apps") // previously "dapps"
	ActionsPath        = path.Join(ErisRoot, "actions")
	ChainsPath         = path.Join(ErisRoot, "chains") // previously "blockchains"
	DataContainersPath = path.Join(ErisRoot, "data")
	FilesPath          = path.Join(ErisRoot, "files")
	KeysPath           = path.Join(ErisRoot, "keys")
	LanguagesPath      = path.Join(ErisRoot, "languages")
	ServicesPath       = path.Join(ErisRoot, "services")
	ScratchPath        = path.Join(ErisRoot, "scratch")

	//Deprecated Directories
	BlockchainsPath = path.Join(ErisRoot, "blockchains")
	DappsPath       = path.Join(ErisRoot, "dapps")

	// Keys
	KeysDataPath = path.Join(KeysPath, "data")
	KeyNamesPath = path.Join(KeysPath, "names")

	// Scratch Directories (globally coordinated)
	EpmScratchPath  = path.Join(ScratchPath, "epm")
	LllcScratchPath = path.Join(ScratchPath, "lllc")
	SolcScratchPath = path.Join(ScratchPath, "sol")
	SerpScratchPath = path.Join(ScratchPath, "ser")

	// Blockchains stuff
	HEAD = path.Join(BlockchainsPath, "HEAD")
	Refs = path.Join(BlockchainsPath, "refs")
)

var MajorDirs = []string{
	ErisRoot, ActionsPath, BlockchainsPath, DataContainersPath, AppsPath, FilesPath, KeysPath, LanguagesPath, ServicesPath, KeysDataPath, KeyNamesPath, ScratchPath, EpmScratchPath, LllcScratchPath, SolcScratchPath, SerpScratchPath,
}

//---------------------------------------------
// user and process

func Usr() string {
	u, _ := homedir.Dir()
	return u
}

func Exit(err error) {
	status := 0
	if err != nil {
		log.Flush()
		fmt.Println(err)
		status = 1
	}
	os.Exit(status)
}

func IfExit(err error) {
	if err != nil {
		log.Flush()
		fmt.Println(err)
		os.Exit(1)
	}
}

// user and process
//---------------------------------------------------------------------------
// filesystem

func AbsolutePath(Datadir string, filename string) string {
	if path.IsAbs(filename) {
		return filename
	}
	return path.Join(Datadir, filename)
}

func InitDataDir(Datadir string) error {
	if _, err := os.Stat(Datadir); err != nil {
		if os.IsNotExist(err) {
			if err := os.MkdirAll(Datadir, 0777); err != nil {
				return err
			}
		}
	}
	return nil
}

func ResolveErisRoot() string {
	var eris string
	if os.Getenv("ERIS") != "" {
		eris = os.Getenv("ERIS")
	} else {
		if runtime.GOOS == "windows" {
			home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
			if home == "" {
				home = os.Getenv("USERPROFILE")
			}
			eris = path.Join(home, ".eris")
		} else {
			eris = path.Join(Usr(), ".eris")
		}
	}
	return eris
}

// Create the default eris tree
func InitErisDir() (err error) {
	for _, d := range MajorDirs {
		err := InitDataDir(d)
		if err != nil {
			return err
		}
	}
	if _, err = os.Stat(HEAD); err != nil {
		_, err = os.Create(HEAD)
	}
	return
}

func ClearDir(dir string) error {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, f := range fs {
		n := f.Name()
		if f.IsDir() {
			if err := os.RemoveAll(path.Join(dir, f.Name())); err != nil {
				return err
			}
		} else {
			if err := os.Remove(path.Join(dir, n)); err != nil {
				return err
			}
		}
	}
	return nil
}

func Copy(src, dst string) error {
	f, err := os.Stat(src)
	if err != nil {
		return err
	}
	if f.IsDir() {
		tmpDir, err := ioutil.TempDir(os.TempDir(), "eris_copy")
		if err != nil {
			return err
		}
		if err := copyDir(src, tmpDir); err != nil {
			return err
		}
		if err := copyDir(tmpDir, dst); err != nil {
			return err
		}
		// fi, err := os.Stat(src)
		// if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		// 	return err
		// }
		// return os.Rename(tmpDir, dst)
		return nil
	}
	return copyFile(src, dst)
}

// assumes we've done our checking
func copyDir(src, dst string) error {
	fi, err := os.Stat(src)
	if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		return err
	}
	fs, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}

	for _, f := range fs {
		s := path.Join(src, f.Name())
		d := path.Join(dst, f.Name())
		if f.IsDir() {
			if err := copyDir(s, d); err != nil {
				return err
			}
		} else {
			if err := copyFile(s, d); err != nil {
				return err
			}
		}
	}
	return nil
}

// common golang, really?
func copyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func WriteFile(data, path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
		return err
	}
	writer, err := os.Create(filepath.Join(path))
	defer writer.Close()
	if err != nil {
		return err
	}
	writer.Write([]byte(data))
	return nil
}

// filesystem
//-------------------------------------------------------
// open text editors

func Editor(file string) error {
	editr := os.Getenv("EDITOR")
	if strings.Contains(editr, "/") {
		editr = path.Base(editr)
	}
	switch editr {
	case "", "vim", "vi":
		return vi(file)
	case "emacs":
		return emacs(file)
	default:
		return editor(file)
	}
	// return fmt.Errorf("Unknown editor %s", editr)
}

func emacs(file string) error {
	cmd := exec.Command("emacs", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func vi(file string) error {
	cmd := exec.Command("vim", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func editor(file string) error {
	cmd := exec.Command(os.Getenv("EDITOR"), file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

//
// engine.PGPKeyImportEngine is a class for optionally generating PGP keys,
// and pushing them into the keybase sigchain via the Delegator.
//

import (
	"errors"
	"os/exec"
	"strings"

	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
)

type PGPKeyImportEngine struct {
	me     *libkb.User
	bundle *libkb.PGPKeyBundle
	arg    PGPKeyImportEngineArg
	epk    string
	del    *libkb.Delegator
	libkb.Contextified
}

type PGPKeyImportEngineArg struct {
	Gen        *libkb.PGPGenArg
	Pregen     *libkb.PGPKeyBundle
	SigningKey libkb.GenericKey
	Me         *libkb.User
	Ctx        *libkb.GlobalContext
	Lks        *libkb.LKSec
	NoSave     bool
	PushSecret bool
	OnlySave   bool
	AllowMulti bool
	DoExport   bool
	DoUnlock   bool
}

func NewPGPKeyImportEngineFromBytes(key []byte, pushPrivate bool, gc *libkb.GlobalContext) (eng *PGPKeyImportEngine, err error) {
	var bundle *libkb.PGPKeyBundle
	if libkb.IsArmored(key) {
		bundle, err = libkb.ReadPrivateKeyFromString(string(key))
	} else {
		bundle, err = libkb.ReadOneKeyFromBytes(key)
	}
	if err != nil {
		return
	}
	arg := PGPKeyImportEngineArg{
		Pregen:     bundle,
		PushSecret: pushPrivate,
		AllowMulti: true,
		DoExport:   false,
		DoUnlock:   true,
		Ctx:        gc,
	}
	eng = NewPGPKeyImportEngine(arg)
	return
}

func (e *PGPKeyImportEngine) loadMe() (err error) {
	if e.me = e.arg.Me; e.me != nil {
		return
	}
	e.me, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(e.G()))
	return err
}

func (e *PGPKeyImportEngine) loadLoginSession(ctx *Context) error {
	var err error
	if ctx.LoginContext != nil {
		err = ctx.LoginContext.LoadLoginSession(e.me.GetName())
	} else {
		aerr := e.G().LoginState().Account(func(a *libkb.Account) {
			err = a.LoadLoginSession(e.me.GetName())
		}, "PGPKeyImportEngine - loadLoginSession")
		if aerr != nil {
			return aerr
		}
	}
	return err
}

func (e *PGPKeyImportEngine) generateKey(ctx *Context) (err error) {
	gen := e.arg.Gen
	if err = gen.CreatePGPIDs(); err != nil {
		return
	}
	e.bundle, err = libkb.GeneratePGPKeyBundle(*gen, ctx.LogUI)
	return
}

func (e *PGPKeyImportEngine) saveLKS(ctx *Context) (err error) {
	e.G().Log.Debug("+ PGPKeyImportEngine::saveLKS")
	defer func() {
		e.G().Log.Debug("- PGPKeyImportEngine::saveLKS -> %v", libkb.ErrToOk(err))
	}()

	lks := e.arg.Lks
	if lks == nil {
		lks, err = libkb.NewLKSForEncrypt(ctx.SecretUI, e.me.GetUID(), e.G())
		if err != nil {
			return err
		}
	}
	_, err = libkb.WriteLksSKBToKeyring(e.G(), e.bundle, lks, ctx.LoginContext)
	return
}

var ErrKeyGenArgNoDefNoCustom = errors.New("invalid args:  NoDefPGPUid set, but no custom PGPUids")

func NewPGPKeyImportEngine(arg PGPKeyImportEngineArg) *PGPKeyImportEngine {
	return &PGPKeyImportEngine{arg: arg, Contextified: libkb.NewContextified(arg.Ctx)}
}

func (e *PGPKeyImportEngine) Name() string {
	return "PGPKeyImportEngine"
}

func (e *PGPKeyImportEngine) Prereqs() Prereqs {
	return Prereqs{
		Session: true,
	}
}

func (e *PGPKeyImportEngine) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{
		libkb.LogUIKind,
		libkb.SecretUIKind,
	}
}

func (e *PGPKeyImportEngine) SubConsumers() []libkb.UIConsumer {
	return nil
}

func (e *PGPKeyImportEngine) init() (err error) {
	if e.arg.Gen != nil {
		err = e.arg.Gen.Init()
	}
	return err
}

func (e *PGPKeyImportEngine) testExisting() (err error) {
	return PGPCheckMulti(e.me, e.arg.AllowMulti)
}

// checkPregenPrivate makes sure that the pregenerated key is a
// private key.
func (e *PGPKeyImportEngine) checkPregenPrivate() error {
	if e.arg.Pregen == nil {
		return nil
	}
	if e.arg.Pregen.HasSecretKey() {
		return nil
	}
	return libkb.NoSecretKeyError{}
}

func (e *PGPKeyImportEngine) Run(ctx *Context) error {
	e.G().Log.Debug("+ PGPKeyImportEngine::Run")
	defer func() {
		e.G().Log.Debug("- PGPKeyImportEngine::Run")
	}()

	if err := e.init(); err != nil {
		return err
	}

	if err := e.loadMe(); err != nil {
		return err
	}

	if err := e.loadLoginSession(ctx); err != nil {
		return err
	}

	if err := e.checkPregenPrivate(); err != nil {
		return err
	}

	if !e.arg.OnlySave {
		if err := e.testExisting(); err != nil {
			return err
		}

		if err := e.loadDelegator(ctx); err != nil {
			return err
		}
	}

	if err := e.unlock(ctx); err != nil {
		return err
	}

	if err := e.generate(ctx); err != nil {
		return err
	}

	if !e.arg.OnlySave {
		if err := e.push(ctx); err != nil {
			return err
		}

		if err := e.exportToGPG(ctx); err != nil {
			return err
		}
	}

	return nil
}

func (e *PGPKeyImportEngine) exportToGPG(ctx *Context) (err error) {
	if !e.arg.DoExport || e.arg.Pregen != nil {
		e.G().Log.Debug("| Skipping export to GPG")
		return
	}
	gpg := e.G().GetGpgClient()

	if err := gpg.Configure(); err != nil {
		if err == exec.ErrNotFound {
			e.G().Log.Debug("Not saving new key to GPG since no gpg install was found")
			err = nil
		}
		return err
	}
	err = gpg.ExportKey(*e.bundle, true /* export private key */)
	if err == nil {
		ctx.LogUI.Info("Exported new key to the local GPG keychain")
	}
	return err
}

func (e *PGPKeyImportEngine) unlock(ctx *Context) (err error) {
	e.G().Log.Debug("+ PGPKeyImportEngine::unlock")
	defer func() {
		e.G().Log.Debug("- PGPKeyImportEngine::unlock -> %s", libkb.ErrToOk(err))
	}()
	if e.arg.Pregen == nil || !e.arg.DoUnlock || !e.arg.Pregen.HasSecretKey() {
		e.G().Log.Debug("| short circuit unlock function")
	} else {
		err = e.arg.Pregen.Unlock("import into private keychain", ctx.SecretUI)
	}
	return

}

func (e *PGPKeyImportEngine) loadDelegator(ctx *Context) (err error) {

	e.del = &libkb.Delegator{
		ExistingKey:    e.arg.SigningKey,
		Me:             e.me,
		Expire:         libkb.KeyExpireIn,
		DelegationType: libkb.SibkeyType,
		Contextified:   libkb.NewContextified(e.G()),
	}

	return e.del.LoadSigningKey(ctx.LoginContext, ctx.SecretUI)
}

func (e *PGPKeyImportEngine) generate(ctx *Context) (err error) {

	e.G().Log.Debug("+ PGP::Generate")
	defer func() {
		e.G().Log.Debug("- PGP::Generate -> %s", libkb.ErrToOk(err))
	}()

	e.G().Log.Debug("| GenerateKey")
	if e.arg.Pregen != nil {
		e.bundle = e.arg.Pregen
	} else if e.arg.Gen == nil {
		err = libkb.InternalError{Msg: "PGPKeyImportEngine: need either Gen or Pregen"}
		return
	} else if err = e.generateKey(ctx); err != nil {
		return
	}

	e.G().Log.Debug("| WriteKey (hasSecret = %v)", e.bundle.HasSecretKey())
	if !e.arg.NoSave && e.bundle.HasSecretKey() {
		if err = e.saveLKS(ctx); err != nil {
			return
		}
	}

	if e.arg.PushSecret {
		if err = e.prepareSecretPush(ctx); err != nil {
			return
		}
	}
	return

}

func (e *PGPKeyImportEngine) prepareSecretPush(ctx *Context) error {
	tsec, gen, err := e.G().LoginState().GetVerifiedTriplesec(ctx.SecretUI)
	if err != nil {
		return err
	}
	skb, err := e.bundle.ToServerSKB(e.G(), tsec, gen)
	if err != nil {
		return err
	}
	e.epk, err = skb.ArmoredEncode()

	return err
}

func (e *PGPKeyImportEngine) push(ctx *Context) (err error) {
	e.G().Log.Debug("+ PGP::Push")
	e.del.NewKey = e.bundle
	e.del.EncodedPrivateKey = e.epk
	if err = e.del.Run(ctx.LoginContext); err != nil {
		return err
	}
	e.G().Log.Debug("- PGP::Push -> %s", libkb.ErrToOk(err))

	ctx.LogUI.Info("Generated new PGP key:")
	d := e.bundle.VerboseDescription()
	for _, line := range strings.Split(d, "\n") {
		ctx.LogUI.Info("  %s", line)
	}

	return nil
}

func PGPCheckMulti(me *libkb.User, allowMulti bool) (err error) {
	if allowMulti {
		return
	}
	if pgps := me.GetActivePGPKeys(false); len(pgps) > 0 {
		err = libkb.KeyExistsError{Key: pgps[0].GetFingerprintP()}
	}
	return
}

func (e *PGPKeyImportEngine) GetKID() (kid keybase1.KID) {
	if e.bundle == nil {
		return kid
	}
	return e.bundle.GetKID()
}
<commit_msg>Fix gpg check in exportToGPG<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package engine

//
// engine.PGPKeyImportEngine is a class for optionally generating PGP keys,
// and pushing them into the keybase sigchain via the Delegator.
//

import (
	"errors"
	"strings"

	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
)

type PGPKeyImportEngine struct {
	me     *libkb.User
	bundle *libkb.PGPKeyBundle
	arg    PGPKeyImportEngineArg
	epk    string
	del    *libkb.Delegator
	libkb.Contextified
}

type PGPKeyImportEngineArg struct {
	Gen        *libkb.PGPGenArg
	Pregen     *libkb.PGPKeyBundle
	SigningKey libkb.GenericKey
	Me         *libkb.User
	Ctx        *libkb.GlobalContext
	Lks        *libkb.LKSec
	NoSave     bool
	PushSecret bool
	OnlySave   bool
	AllowMulti bool
	DoExport   bool
	DoUnlock   bool
}

func NewPGPKeyImportEngineFromBytes(key []byte, pushPrivate bool, gc *libkb.GlobalContext) (eng *PGPKeyImportEngine, err error) {
	var bundle *libkb.PGPKeyBundle
	if libkb.IsArmored(key) {
		bundle, err = libkb.ReadPrivateKeyFromString(string(key))
	} else {
		bundle, err = libkb.ReadOneKeyFromBytes(key)
	}
	if err != nil {
		return
	}
	arg := PGPKeyImportEngineArg{
		Pregen:     bundle,
		PushSecret: pushPrivate,
		AllowMulti: true,
		DoExport:   false,
		DoUnlock:   true,
		Ctx:        gc,
	}
	eng = NewPGPKeyImportEngine(arg)
	return
}

func (e *PGPKeyImportEngine) loadMe() (err error) {
	if e.me = e.arg.Me; e.me != nil {
		return
	}
	e.me, err = libkb.LoadMe(libkb.NewLoadUserPubOptionalArg(e.G()))
	return err
}

func (e *PGPKeyImportEngine) loadLoginSession(ctx *Context) error {
	var err error
	if ctx.LoginContext != nil {
		err = ctx.LoginContext.LoadLoginSession(e.me.GetName())
	} else {
		aerr := e.G().LoginState().Account(func(a *libkb.Account) {
			err = a.LoadLoginSession(e.me.GetName())
		}, "PGPKeyImportEngine - loadLoginSession")
		if aerr != nil {
			return aerr
		}
	}
	return err
}

func (e *PGPKeyImportEngine) generateKey(ctx *Context) (err error) {
	gen := e.arg.Gen
	if err = gen.CreatePGPIDs(); err != nil {
		return
	}
	e.bundle, err = libkb.GeneratePGPKeyBundle(*gen, ctx.LogUI)
	return
}

func (e *PGPKeyImportEngine) saveLKS(ctx *Context) (err error) {
	e.G().Log.Debug("+ PGPKeyImportEngine::saveLKS")
	defer func() {
		e.G().Log.Debug("- PGPKeyImportEngine::saveLKS -> %v", libkb.ErrToOk(err))
	}()

	lks := e.arg.Lks
	if lks == nil {
		lks, err = libkb.NewLKSForEncrypt(ctx.SecretUI, e.me.GetUID(), e.G())
		if err != nil {
			return err
		}
	}
	_, err = libkb.WriteLksSKBToKeyring(e.G(), e.bundle, lks, ctx.LoginContext)
	return
}

var ErrKeyGenArgNoDefNoCustom = errors.New("invalid args:  NoDefPGPUid set, but no custom PGPUids")

func NewPGPKeyImportEngine(arg PGPKeyImportEngineArg) *PGPKeyImportEngine {
	return &PGPKeyImportEngine{arg: arg, Contextified: libkb.NewContextified(arg.Ctx)}
}

func (e *PGPKeyImportEngine) Name() string {
	return "PGPKeyImportEngine"
}

func (e *PGPKeyImportEngine) Prereqs() Prereqs {
	return Prereqs{
		Session: true,
	}
}

func (e *PGPKeyImportEngine) RequiredUIs() []libkb.UIKind {
	return []libkb.UIKind{
		libkb.LogUIKind,
		libkb.SecretUIKind,
	}
}

func (e *PGPKeyImportEngine) SubConsumers() []libkb.UIConsumer {
	return nil
}

func (e *PGPKeyImportEngine) init() (err error) {
	if e.arg.Gen != nil {
		err = e.arg.Gen.Init()
	}
	return err
}

func (e *PGPKeyImportEngine) testExisting() (err error) {
	return PGPCheckMulti(e.me, e.arg.AllowMulti)
}

// checkPregenPrivate makes sure that the pregenerated key is a
// private key.
func (e *PGPKeyImportEngine) checkPregenPrivate() error {
	if e.arg.Pregen == nil {
		return nil
	}
	if e.arg.Pregen.HasSecretKey() {
		return nil
	}
	return libkb.NoSecretKeyError{}
}

func (e *PGPKeyImportEngine) Run(ctx *Context) error {
	e.G().Log.Debug("+ PGPKeyImportEngine::Run")
	defer func() {
		e.G().Log.Debug("- PGPKeyImportEngine::Run")
	}()

	if err := e.init(); err != nil {
		return err
	}

	if err := e.loadMe(); err != nil {
		return err
	}

	if err := e.loadLoginSession(ctx); err != nil {
		return err
	}

	if err := e.checkPregenPrivate(); err != nil {
		return err
	}

	if !e.arg.OnlySave {
		if err := e.testExisting(); err != nil {
			return err
		}

		if err := e.loadDelegator(ctx); err != nil {
			return err
		}
	}

	if err := e.unlock(ctx); err != nil {
		return err
	}

	if err := e.generate(ctx); err != nil {
		return err
	}

	if !e.arg.OnlySave {
		if err := e.push(ctx); err != nil {
			return err
		}

		if err := e.exportToGPG(ctx); err != nil {
			return err
		}
	}

	return nil
}

func (e *PGPKeyImportEngine) exportToGPG(ctx *Context) (err error) {
	if !e.arg.DoExport || e.arg.Pregen != nil {
		e.G().Log.Debug("| Skipping export to GPG")
		return
	}
	gpg := e.G().GetGpgClient()

	ok, err := gpg.CanExec()
	if err != nil {
		e.G().Log.Debug("Not saving new key to GPG. Error in gpg.CanExec(): %s", err)
		// libkb/util_*.go:canExec() can return generic errors, just ignore them
		// in this situation since export to gpg is on by default in the client
		// pgp gen command.
		return nil
	}
	if !ok {
		e.G().Log.Debug("Not saving new key to GPG since no gpg install was found")
		return nil
	}

	err = gpg.ExportKey(*e.bundle, true /* export private key */)
	if err == nil {
		ctx.LogUI.Info("Exported new key to the local GPG keychain")
	}
	return err
}

func (e *PGPKeyImportEngine) unlock(ctx *Context) (err error) {
	e.G().Log.Debug("+ PGPKeyImportEngine::unlock")
	defer func() {
		e.G().Log.Debug("- PGPKeyImportEngine::unlock -> %s", libkb.ErrToOk(err))
	}()
	if e.arg.Pregen == nil || !e.arg.DoUnlock || !e.arg.Pregen.HasSecretKey() {
		e.G().Log.Debug("| short circuit unlock function")
	} else {
		err = e.arg.Pregen.Unlock("import into private keychain", ctx.SecretUI)
	}
	return

}

func (e *PGPKeyImportEngine) loadDelegator(ctx *Context) (err error) {

	e.del = &libkb.Delegator{
		ExistingKey:    e.arg.SigningKey,
		Me:             e.me,
		Expire:         libkb.KeyExpireIn,
		DelegationType: libkb.SibkeyType,
		Contextified:   libkb.NewContextified(e.G()),
	}

	return e.del.LoadSigningKey(ctx.LoginContext, ctx.SecretUI)
}

func (e *PGPKeyImportEngine) generate(ctx *Context) (err error) {

	e.G().Log.Debug("+ PGP::Generate")
	defer func() {
		e.G().Log.Debug("- PGP::Generate -> %s", libkb.ErrToOk(err))
	}()

	e.G().Log.Debug("| GenerateKey")
	if e.arg.Pregen != nil {
		e.bundle = e.arg.Pregen
	} else if e.arg.Gen == nil {
		err = libkb.InternalError{Msg: "PGPKeyImportEngine: need either Gen or Pregen"}
		return
	} else if err = e.generateKey(ctx); err != nil {
		return
	}

	e.G().Log.Debug("| WriteKey (hasSecret = %v)", e.bundle.HasSecretKey())
	if !e.arg.NoSave && e.bundle.HasSecretKey() {
		if err = e.saveLKS(ctx); err != nil {
			return
		}
	}

	if e.arg.PushSecret {
		if err = e.prepareSecretPush(ctx); err != nil {
			return
		}
	}
	return

}

func (e *PGPKeyImportEngine) prepareSecretPush(ctx *Context) error {
	tsec, gen, err := e.G().LoginState().GetVerifiedTriplesec(ctx.SecretUI)
	if err != nil {
		return err
	}
	skb, err := e.bundle.ToServerSKB(e.G(), tsec, gen)
	if err != nil {
		return err
	}
	e.epk, err = skb.ArmoredEncode()

	return err
}

func (e *PGPKeyImportEngine) push(ctx *Context) (err error) {
	e.G().Log.Debug("+ PGP::Push")
	e.del.NewKey = e.bundle
	e.del.EncodedPrivateKey = e.epk
	if err = e.del.Run(ctx.LoginContext); err != nil {
		return err
	}
	e.G().Log.Debug("- PGP::Push -> %s", libkb.ErrToOk(err))

	ctx.LogUI.Info("Generated new PGP key:")
	d := e.bundle.VerboseDescription()
	for _, line := range strings.Split(d, "\n") {
		ctx.LogUI.Info("  %s", line)
	}

	return nil
}

func PGPCheckMulti(me *libkb.User, allowMulti bool) (err error) {
	if allowMulti {
		return
	}
	if pgps := me.GetActivePGPKeys(false); len(pgps) > 0 {
		err = libkb.KeyExistsError{Key: pgps[0].GetFingerprintP()}
	}
	return
}

func (e *PGPKeyImportEngine) GetKID() (kid keybase1.KID) {
	if e.bundle == nil {
		return kid
	}
	return e.bundle.GetKID()
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Vitess 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 sqlparser

import (
	"strconv"
	"strings"
	"unicode"
)

const (
	// DirectiveMultiShardAutocommit is the query comment directive to allow
	// single round trip autocommit with a multi-shard statement.
	DirectiveMultiShardAutocommit = "MULTI_SHARD_AUTOCOMMIT"
	// DirectiveSkipQueryPlanCache skips query plan cache when set.
	DirectiveSkipQueryPlanCache = "SKIP_QUERY_PLAN_CACHE"
	// DirectiveQueryTimeout sets a query timeout in vtgate. Only supported for SELECTS.
	DirectiveQueryTimeout = "QUERY_TIMEOUT_MS"
	// DirectiveScatterErrorsAsWarnings enables partial success scatter select queries
	DirectiveScatterErrorsAsWarnings = "SCATTER_ERRORS_AS_WARNINGS"
	// DirectiveIgnoreMaxPayloadSize skips payload size validation when set.
	DirectiveIgnoreMaxPayloadSize = "IGNORE_MAX_PAYLOAD_SIZE"
	// DirectiveIgnoreMaxMemoryRows skips memory row validation when set.
	DirectiveIgnoreMaxMemoryRows = "IGNORE_MAX_MEMORY_ROWS"
)

func isNonSpace(r rune) bool {
	return !unicode.IsSpace(r)
}

// leadingCommentEnd returns the first index after all leading comments, or
// 0 if there are no leading comments.
func leadingCommentEnd(text string) (end int) {
	hasComment := false
	pos := 0
	for pos < len(text) {
		// Eat up any whitespace. Trailing whitespace will be considered part of
		// the leading comments.
		nextVisibleOffset := strings.IndexFunc(text[pos:], isNonSpace)
		if nextVisibleOffset < 0 {
			break
		}
		pos += nextVisibleOffset
		remainingText := text[pos:]

		// Found visible characters. Look for '/*' at the beginning
		// and '*/' somewhere after that.
		if len(remainingText) < 4 || remainingText[:2] != "/*" || remainingText[2] == '!' {
			break
		}
		commentLength := 4 + strings.Index(remainingText[2:], "*/")
		if commentLength < 4 {
			// Missing end comment :/
			break
		}

		hasComment = true
		pos += commentLength
	}

	if hasComment {
		return pos
	}
	return 0
}

// trailingCommentStart returns the first index of trailing comments.
// If there are no trailing comments, returns the length of the input string.
func trailingCommentStart(text string) (start int) {
	hasComment := false
	reducedLen := len(text)
	for reducedLen > 0 {
		// Eat up any whitespace. Leading whitespace will be considered part of
		// the trailing comments.
		nextReducedLen := strings.LastIndexFunc(text[:reducedLen], isNonSpace) + 1
		if nextReducedLen == 0 {
			break
		}
		reducedLen = nextReducedLen
		if reducedLen < 4 || text[reducedLen-2:reducedLen] != "*/" {
			break
		}

		// Find the beginning of the comment
		startCommentPos := strings.LastIndex(text[:reducedLen-2], "/*")
		if startCommentPos < 0 || text[startCommentPos+2] == '!' {
			// Badly formatted sql, or a special /*! comment
			break
		}

		hasComment = true
		reducedLen = startCommentPos
	}

	if hasComment {
		return reducedLen
	}
	return len(text)
}

// MarginComments holds the leading and trailing comments that surround a query.
type MarginComments struct {
	Leading  string
	Trailing string
}

// SplitMarginComments pulls out any leading or trailing comments from a raw sql query.
// This function also trims leading (if there's a comment) and trailing whitespace.
func SplitMarginComments(sql string) (query string, comments MarginComments) {
	trailingStart := trailingCommentStart(sql)
	leadingEnd := leadingCommentEnd(sql[:trailingStart])
	comments = MarginComments{
		Leading:  strings.TrimLeftFunc(sql[:leadingEnd], unicode.IsSpace),
		Trailing: strings.TrimRightFunc(sql[trailingStart:], unicode.IsSpace),
	}
	return strings.TrimFunc(sql[leadingEnd:trailingStart], func(c rune) bool {
		return unicode.IsSpace(c) || c == ';'
	}), comments
}

// StripLeadingComments trims the SQL string and removes any leading comments
func StripLeadingComments(sql string) string {
	sql = strings.TrimFunc(sql, unicode.IsSpace)

	for hasCommentPrefix(sql) {
		switch sql[0] {
		case '/':
			// Multi line comment
			index := strings.Index(sql, "*/")
			if index <= 1 {
				return sql
			}
			// don't strip /*! ... */ or /*!50700 ... */
			if len(sql) > 2 && sql[2] == '!' {
				return sql
			}
			sql = sql[index+2:]
		case '-':
			// Single line comment
			index := strings.Index(sql, "\n")
			if index == -1 {
				return ""
			}
			sql = sql[index+1:]
		}

		sql = strings.TrimFunc(sql, unicode.IsSpace)
	}

	return sql
}

func hasCommentPrefix(sql string) bool {
	return len(sql) > 1 && ((sql[0] == '/' && sql[1] == '*') || (sql[0] == '-' && sql[1] == '-'))
}

// ExtractMysqlComment extracts the version and SQL from a comment-only query
// such as /*!50708 sql here */
func ExtractMysqlComment(sql string) (string, string) {
	sql = sql[3 : len(sql)-2]

	digitCount := 0
	endOfVersionIndex := strings.IndexFunc(sql, func(c rune) bool {
		digitCount++
		return !unicode.IsDigit(c) || digitCount == 6
	})
	if endOfVersionIndex < 0 {
		return "", ""
	}
	version := sql[0:endOfVersionIndex]
	innerSQL := strings.TrimFunc(sql[endOfVersionIndex:], unicode.IsSpace)

	return version, innerSQL
}

const commentDirectivePreamble = "/*vt+"

// CommentDirectives is the parsed representation for execution directives
// conveyed in query comments
type CommentDirectives map[string]interface{}

// ExtractCommentDirectives parses the comment list for any execution directives
// of the form:
//
//     /*vt+ OPTION_ONE=1 OPTION_TWO OPTION_THREE=abcd */
//
// It returns the map of the directive values or nil if there aren't any.
func ExtractCommentDirectives(comments Comments) CommentDirectives {
	if comments == nil {
		return nil
	}

	var vals map[string]interface{}

	for _, comment := range comments {
		commentStr := string(comment)
		if commentStr[0:5] != commentDirectivePreamble {
			continue
		}

		if vals == nil {
			vals = make(map[string]interface{})
		}

		// Split on whitespace and ignore the first and last directive
		// since they contain the comment start/end
		directives := strings.Fields(commentStr)
		for i := 1; i < len(directives)-1; i++ {
			directive := directives[i]
			sep := strings.IndexByte(directive, '=')

			// No value is equivalent to a true boolean
			if sep == -1 {
				vals[directive] = true
				continue
			}

			strVal := directive[sep+1:]
			directive = directive[:sep]

			intVal, err := strconv.Atoi(strVal)
			if err == nil {
				vals[directive] = intVal
				continue
			}

			boolVal, err := strconv.ParseBool(strVal)
			if err == nil {
				vals[directive] = boolVal
				continue
			}

			vals[directive] = strVal
		}
	}
	return vals
}

// IsSet checks the directive map for the named directive and returns
// true if the directive is set and has a true/false or 0/1 value
func (d CommentDirectives) IsSet(key string) bool {
	if d == nil {
		return false
	}

	val, ok := d[key]
	if !ok {
		return false
	}

	boolVal, ok := val.(bool)
	if ok {
		return boolVal
	}

	intVal, ok := val.(int)
	if ok {
		return intVal == 1
	}
	return false
}

// SkipQueryPlanCacheDirective returns true if skip query plan cache directive is set to true in query.
func SkipQueryPlanCacheDirective(stmt Statement) bool {
	switch stmt := stmt.(type) {
	case *Select:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	case *Insert:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	case *Update:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	case *Delete:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	default:
		return false
	}
	return false
}

// IgnoreMaxPayloadSizeDirective returns true if the max payload size override
// directive is set to true.
func IgnoreMaxPayloadSizeDirective(stmt Statement) bool {
	switch stmt := stmt.(type) {
	case *Select:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	case *Insert:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	case *Update:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	case *Delete:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	default:
		return false
	}
}

// IgnoreMaxMaxMemoryRowsDirective returns true if the max memory rows override
// directive is set to true.
func IgnoreMaxMaxMemoryRowsDirective(stmt Statement) bool {
	switch stmt := stmt.(type) {
	case *Select:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	case *Insert:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	case *Update:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	case *Delete:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	default:
		return false
	}
}
<commit_msg>add MultiShardAutocommitDirective utility<commit_after>/*
Copyright 2019 The Vitess 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 sqlparser

import (
	"strconv"
	"strings"
	"unicode"
)

const (
	// DirectiveMultiShardAutocommit is the query comment directive to allow
	// single round trip autocommit with a multi-shard statement.
	DirectiveMultiShardAutocommit = "MULTI_SHARD_AUTOCOMMIT"
	// DirectiveSkipQueryPlanCache skips query plan cache when set.
	DirectiveSkipQueryPlanCache = "SKIP_QUERY_PLAN_CACHE"
	// DirectiveQueryTimeout sets a query timeout in vtgate. Only supported for SELECTS.
	DirectiveQueryTimeout = "QUERY_TIMEOUT_MS"
	// DirectiveScatterErrorsAsWarnings enables partial success scatter select queries
	DirectiveScatterErrorsAsWarnings = "SCATTER_ERRORS_AS_WARNINGS"
	// DirectiveIgnoreMaxPayloadSize skips payload size validation when set.
	DirectiveIgnoreMaxPayloadSize = "IGNORE_MAX_PAYLOAD_SIZE"
	// DirectiveIgnoreMaxMemoryRows skips memory row validation when set.
	DirectiveIgnoreMaxMemoryRows = "IGNORE_MAX_MEMORY_ROWS"
)

func isNonSpace(r rune) bool {
	return !unicode.IsSpace(r)
}

// leadingCommentEnd returns the first index after all leading comments, or
// 0 if there are no leading comments.
func leadingCommentEnd(text string) (end int) {
	hasComment := false
	pos := 0
	for pos < len(text) {
		// Eat up any whitespace. Trailing whitespace will be considered part of
		// the leading comments.
		nextVisibleOffset := strings.IndexFunc(text[pos:], isNonSpace)
		if nextVisibleOffset < 0 {
			break
		}
		pos += nextVisibleOffset
		remainingText := text[pos:]

		// Found visible characters. Look for '/*' at the beginning
		// and '*/' somewhere after that.
		if len(remainingText) < 4 || remainingText[:2] != "/*" || remainingText[2] == '!' {
			break
		}
		commentLength := 4 + strings.Index(remainingText[2:], "*/")
		if commentLength < 4 {
			// Missing end comment :/
			break
		}

		hasComment = true
		pos += commentLength
	}

	if hasComment {
		return pos
	}
	return 0
}

// trailingCommentStart returns the first index of trailing comments.
// If there are no trailing comments, returns the length of the input string.
func trailingCommentStart(text string) (start int) {
	hasComment := false
	reducedLen := len(text)
	for reducedLen > 0 {
		// Eat up any whitespace. Leading whitespace will be considered part of
		// the trailing comments.
		nextReducedLen := strings.LastIndexFunc(text[:reducedLen], isNonSpace) + 1
		if nextReducedLen == 0 {
			break
		}
		reducedLen = nextReducedLen
		if reducedLen < 4 || text[reducedLen-2:reducedLen] != "*/" {
			break
		}

		// Find the beginning of the comment
		startCommentPos := strings.LastIndex(text[:reducedLen-2], "/*")
		if startCommentPos < 0 || text[startCommentPos+2] == '!' {
			// Badly formatted sql, or a special /*! comment
			break
		}

		hasComment = true
		reducedLen = startCommentPos
	}

	if hasComment {
		return reducedLen
	}
	return len(text)
}

// MarginComments holds the leading and trailing comments that surround a query.
type MarginComments struct {
	Leading  string
	Trailing string
}

// SplitMarginComments pulls out any leading or trailing comments from a raw sql query.
// This function also trims leading (if there's a comment) and trailing whitespace.
func SplitMarginComments(sql string) (query string, comments MarginComments) {
	trailingStart := trailingCommentStart(sql)
	leadingEnd := leadingCommentEnd(sql[:trailingStart])
	comments = MarginComments{
		Leading:  strings.TrimLeftFunc(sql[:leadingEnd], unicode.IsSpace),
		Trailing: strings.TrimRightFunc(sql[trailingStart:], unicode.IsSpace),
	}
	return strings.TrimFunc(sql[leadingEnd:trailingStart], func(c rune) bool {
		return unicode.IsSpace(c) || c == ';'
	}), comments
}

// StripLeadingComments trims the SQL string and removes any leading comments
func StripLeadingComments(sql string) string {
	sql = strings.TrimFunc(sql, unicode.IsSpace)

	for hasCommentPrefix(sql) {
		switch sql[0] {
		case '/':
			// Multi line comment
			index := strings.Index(sql, "*/")
			if index <= 1 {
				return sql
			}
			// don't strip /*! ... */ or /*!50700 ... */
			if len(sql) > 2 && sql[2] == '!' {
				return sql
			}
			sql = sql[index+2:]
		case '-':
			// Single line comment
			index := strings.Index(sql, "\n")
			if index == -1 {
				return ""
			}
			sql = sql[index+1:]
		}

		sql = strings.TrimFunc(sql, unicode.IsSpace)
	}

	return sql
}

func hasCommentPrefix(sql string) bool {
	return len(sql) > 1 && ((sql[0] == '/' && sql[1] == '*') || (sql[0] == '-' && sql[1] == '-'))
}

// ExtractMysqlComment extracts the version and SQL from a comment-only query
// such as /*!50708 sql here */
func ExtractMysqlComment(sql string) (string, string) {
	sql = sql[3 : len(sql)-2]

	digitCount := 0
	endOfVersionIndex := strings.IndexFunc(sql, func(c rune) bool {
		digitCount++
		return !unicode.IsDigit(c) || digitCount == 6
	})
	if endOfVersionIndex < 0 {
		return "", ""
	}
	version := sql[0:endOfVersionIndex]
	innerSQL := strings.TrimFunc(sql[endOfVersionIndex:], unicode.IsSpace)

	return version, innerSQL
}

const commentDirectivePreamble = "/*vt+"

// CommentDirectives is the parsed representation for execution directives
// conveyed in query comments
type CommentDirectives map[string]interface{}

// ExtractCommentDirectives parses the comment list for any execution directives
// of the form:
//
//     /*vt+ OPTION_ONE=1 OPTION_TWO OPTION_THREE=abcd */
//
// It returns the map of the directive values or nil if there aren't any.
func ExtractCommentDirectives(comments Comments) CommentDirectives {
	if comments == nil {
		return nil
	}

	var vals map[string]interface{}

	for _, comment := range comments {
		commentStr := string(comment)
		if commentStr[0:5] != commentDirectivePreamble {
			continue
		}

		if vals == nil {
			vals = make(map[string]interface{})
		}

		// Split on whitespace and ignore the first and last directive
		// since they contain the comment start/end
		directives := strings.Fields(commentStr)
		for i := 1; i < len(directives)-1; i++ {
			directive := directives[i]
			sep := strings.IndexByte(directive, '=')

			// No value is equivalent to a true boolean
			if sep == -1 {
				vals[directive] = true
				continue
			}

			strVal := directive[sep+1:]
			directive = directive[:sep]

			intVal, err := strconv.Atoi(strVal)
			if err == nil {
				vals[directive] = intVal
				continue
			}

			boolVal, err := strconv.ParseBool(strVal)
			if err == nil {
				vals[directive] = boolVal
				continue
			}

			vals[directive] = strVal
		}
	}
	return vals
}

// IsSet checks the directive map for the named directive and returns
// true if the directive is set and has a true/false or 0/1 value
func (d CommentDirectives) IsSet(key string) bool {
	if d == nil {
		return false
	}

	val, ok := d[key]
	if !ok {
		return false
	}

	boolVal, ok := val.(bool)
	if ok {
		return boolVal
	}

	intVal, ok := val.(int)
	if ok {
		return intVal == 1
	}
	return false
}

// MultiShardAutocommitDirective returns true if multishard autocommit directive is set to true in query.
func MultiShardAutocommitDirective(stmt Statement) bool {
	switch stmt := stmt.(type) {
	case *Insert:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveMultiShardAutocommit) {
			return true
		}
	case *Update:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveMultiShardAutocommit) {
			return true
		}
	case *Delete:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveMultiShardAutocommit) {
			return true
		}
	default:
		return false
	}
	return false
}

// SkipQueryPlanCacheDirective returns true if skip query plan cache directive is set to true in query.
func SkipQueryPlanCacheDirective(stmt Statement) bool {
	switch stmt := stmt.(type) {
	case *Select:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	case *Insert:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	case *Update:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	case *Delete:
		directives := ExtractCommentDirectives(stmt.Comments)
		if directives.IsSet(DirectiveSkipQueryPlanCache) {
			return true
		}
	default:
		return false
	}
	return false
}

// IgnoreMaxPayloadSizeDirective returns true if the max payload size override
// directive is set to true.
func IgnoreMaxPayloadSizeDirective(stmt Statement) bool {
	switch stmt := stmt.(type) {
	case *Select:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	case *Insert:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	case *Update:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	case *Delete:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxPayloadSize)
	default:
		return false
	}
}

// IgnoreMaxMaxMemoryRowsDirective returns true if the max memory rows override
// directive is set to true.
func IgnoreMaxMaxMemoryRowsDirective(stmt Statement) bool {
	switch stmt := stmt.(type) {
	case *Select:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	case *Insert:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	case *Update:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	case *Delete:
		directives := ExtractCommentDirectives(stmt.Comments)
		return directives.IsSet(DirectiveIgnoreMaxMemoryRows)
	default:
		return false
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/rfjakob/gocryptfs/internal/configfile"
	"github.com/rfjakob/gocryptfs/internal/contentenc"
	"github.com/rfjakob/gocryptfs/internal/cryptocore"
	"github.com/rfjakob/gocryptfs/internal/readpassword"
)

const (
	ivLen     = contentenc.DefaultIVBits / 8
	blockSize = contentenc.DefaultBS + ivLen + cryptocore.AuthTagLen
	myName    = "gocryptfs-xray"
)

func errExit(err error) {
	fmt.Println(err)
	os.Exit(1)
}

func prettyPrintHeader(h *contentenc.FileHeader) {
	id := hex.EncodeToString(h.ID)
	fmt.Printf("Header: Version: %d, Id: %s\n", h.Version, id)
}

func main() {
	dumpmasterkey := flag.Bool("dumpmasterkey", false, "Decrypt and dump the master key")
	flag.Parse()
	if flag.NArg() != 1 {
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] FILE\n"+
			"\n"+
			"Options:\n", myName)
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n"+
			"Examples:\n"+
			"  gocryptfs-xray myfs/mCXnISiv7nEmyc0glGuhTQ\n"+
			"  gocryptfs-xray -dumpmasterkey myfs/gocryptfs.conf\n")
		os.Exit(1)
	}
	fn := flag.Arg(0)
	fd, err := os.Open(fn)
	if err != nil {
		errExit(err)
	}
	defer fd.Close()
	if *dumpmasterkey {
		dumpMasterKey(fn)
	} else {
		inspectCiphertext(fd)
	}
}

func dumpMasterKey(fn string) {
	pw := readpassword.Once("")
	masterkey, _, err := configfile.LoadConfFile(fn, pw)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
	fmt.Println(hex.EncodeToString(masterkey))
}

func inspectCiphertext(fd *os.File) {
	headerBytes := make([]byte, contentenc.HeaderLen)
	n, err := fd.ReadAt(headerBytes, 0)
	if err == io.EOF && n == 0 {
		fmt.Println("empty file")
		os.Exit(0)
	} else if err == io.EOF {
		fmt.Printf("incomplete file header: read %d bytes, want %d\n", n, contentenc.HeaderLen)
		os.Exit(1)
	} else if err != nil {
		errExit(err)
	}
	header, err := contentenc.ParseHeader(headerBytes)
	if err != nil {
		errExit(err)
	}
	prettyPrintHeader(header)
	var i int64
	for i = 0; ; i++ {
		blockLen := int64(blockSize)
		off := contentenc.HeaderLen + i*blockSize
		iv := make([]byte, ivLen)
		_, err := fd.ReadAt(iv, off)
		if err == io.EOF {
			break
		} else if err != nil {
			errExit(err)
		}
		tag := make([]byte, cryptocore.AuthTagLen)
		_, err = fd.ReadAt(tag, off+blockSize-cryptocore.AuthTagLen)
		if err == io.EOF {
			fi, err2 := fd.Stat()
			if err2 != nil {
				errExit(err2)
			}
			_, err2 = fd.ReadAt(tag, fi.Size()-cryptocore.AuthTagLen)
			if err2 != nil {
				errExit(err2)
			}
			blockLen = (fi.Size() - contentenc.HeaderLen) % blockSize
		} else if err != nil {
			errExit(err)
		}
		fmt.Printf("Block %2d: IV: %s, Tag: %s, Offset: %5d Len: %d\n",
			i, hex.EncodeToString(iv), hex.EncodeToString(tag), off, blockLen)
	}
}
<commit_msg>gocryptfs-xray: dumpmasterkey: disable "Reading password from stdin"<commit_after>package main

import (
	"encoding/hex"
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/rfjakob/gocryptfs/internal/configfile"
	"github.com/rfjakob/gocryptfs/internal/contentenc"
	"github.com/rfjakob/gocryptfs/internal/cryptocore"
	"github.com/rfjakob/gocryptfs/internal/exitcodes"
	"github.com/rfjakob/gocryptfs/internal/readpassword"
	"github.com/rfjakob/gocryptfs/internal/tlog"
)

const (
	ivLen     = contentenc.DefaultIVBits / 8
	blockSize = contentenc.DefaultBS + ivLen + cryptocore.AuthTagLen
	myName    = "gocryptfs-xray"
)

func errExit(err error) {
	fmt.Println(err)
	os.Exit(1)
}

func prettyPrintHeader(h *contentenc.FileHeader) {
	id := hex.EncodeToString(h.ID)
	fmt.Printf("Header: Version: %d, Id: %s\n", h.Version, id)
}

func main() {
	dumpmasterkey := flag.Bool("dumpmasterkey", false, "Decrypt and dump the master key")
	flag.Parse()
	if flag.NArg() != 1 {
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] FILE\n"+
			"\n"+
			"Options:\n", myName)
		flag.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n"+
			"Examples:\n"+
			"  gocryptfs-xray myfs/mCXnISiv7nEmyc0glGuhTQ\n"+
			"  gocryptfs-xray -dumpmasterkey myfs/gocryptfs.conf\n")
		os.Exit(1)
	}
	fn := flag.Arg(0)
	fd, err := os.Open(fn)
	if err != nil {
		errExit(err)
	}
	defer fd.Close()
	if *dumpmasterkey {
		dumpMasterKey(fn)
	} else {
		inspectCiphertext(fd)
	}
}

func dumpMasterKey(fn string) {
	tlog.Info.Enabled = false
	pw := readpassword.Once("")
	masterkey, _, err := configfile.LoadConfFile(fn, pw)
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		exitcodes.Exit(err)
	}
	fmt.Println(hex.EncodeToString(masterkey))
}

func inspectCiphertext(fd *os.File) {
	headerBytes := make([]byte, contentenc.HeaderLen)
	n, err := fd.ReadAt(headerBytes, 0)
	if err == io.EOF && n == 0 {
		fmt.Println("empty file")
		os.Exit(0)
	} else if err == io.EOF {
		fmt.Printf("incomplete file header: read %d bytes, want %d\n", n, contentenc.HeaderLen)
		os.Exit(1)
	} else if err != nil {
		errExit(err)
	}
	header, err := contentenc.ParseHeader(headerBytes)
	if err != nil {
		errExit(err)
	}
	prettyPrintHeader(header)
	var i int64
	for i = 0; ; i++ {
		blockLen := int64(blockSize)
		off := contentenc.HeaderLen + i*blockSize
		iv := make([]byte, ivLen)
		_, err := fd.ReadAt(iv, off)
		if err == io.EOF {
			break
		} else if err != nil {
			errExit(err)
		}
		tag := make([]byte, cryptocore.AuthTagLen)
		_, err = fd.ReadAt(tag, off+blockSize-cryptocore.AuthTagLen)
		if err == io.EOF {
			fi, err2 := fd.Stat()
			if err2 != nil {
				errExit(err2)
			}
			_, err2 = fd.ReadAt(tag, fi.Size()-cryptocore.AuthTagLen)
			if err2 != nil {
				errExit(err2)
			}
			blockLen = (fi.Size() - contentenc.HeaderLen) % blockSize
		} else if err != nil {
			errExit(err)
		}
		fmt.Printf("Block %2d: IV: %s, Tag: %s, Offset: %5d Len: %d\n",
			i, hex.EncodeToString(iv), hex.EncodeToString(tag), off, blockLen)
	}
}
<|endoftext|>


<commit_before>package goreleaserlib

import (
	"io/ioutil"
	"log"
	"os"

	yaml "gopkg.in/yaml.v1"

	"fmt"

	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/pipeline"
	"github.com/goreleaser/goreleaser/pipeline/archive"
	"github.com/goreleaser/goreleaser/pipeline/brew"
	"github.com/goreleaser/goreleaser/pipeline/build"
	"github.com/goreleaser/goreleaser/pipeline/checksums"
	"github.com/goreleaser/goreleaser/pipeline/defaults"
	"github.com/goreleaser/goreleaser/pipeline/env"
	"github.com/goreleaser/goreleaser/pipeline/fpm"
	"github.com/goreleaser/goreleaser/pipeline/git"
	"github.com/goreleaser/goreleaser/pipeline/release"
)

var pipes = []pipeline.Pipe{
	defaults.Pipe{},  // load default configs
	git.Pipe{},       // get and validate git repo state
	env.Pipe{},       // load and validate environment variables
	build.Pipe{},     // build
	archive.Pipe{},   // archive (tar.gz, zip, etc)
	fpm.Pipe{},       // archive via fpm (deb, rpm, etc)
	checksums.Pipe{}, // checksums of the files
	release.Pipe{},   // release to github
	brew.Pipe{},      // push to brew tap
}

func init() {
	log.SetFlags(0)
}

// Flags interface represents an extractor of cli flags
type Flags interface {
	IsSet(s string) bool
	String(s string) string
	Bool(s string) bool
}

// Release runs the release process with the given flags
func Release(flags Flags) error {
	var file = flags.String("config")
	var notes = flags.String("release-notes")
	cfg, err := config.Load(file)
	if err != nil {
		// Allow file not found errors if config file was not
		// explicitly specified
		_, statErr := os.Stat(file)
		if !os.IsNotExist(statErr) || flags.IsSet("config") {
			return err
		}
	}
	var ctx = context.New(cfg)
	ctx.Validate = !flags.Bool("skip-validate")
	ctx.Publish = !flags.Bool("skip-publish")
	if notes != "" {
		bts, err := ioutil.ReadFile(notes)
		if err != nil {
			return err
		}
		log.Println("Loaded custom release notes from", notes)
		ctx.ReleaseNotes = string(bts)
	}
	ctx.Snapshot = flags.Bool("snapshot")
	if ctx.Snapshot {
		log.Println("Publishing disabled in snapshot mode")
		ctx.Publish = false
	}
	for _, pipe := range pipes {
		log.Println(pipe.Description())
		log.SetPrefix(" -> ")
		if err := pipe.Run(ctx); err != nil {
			return err
		}
		log.SetPrefix("")
	}
	log.Println("Done!")
	return nil
}

// InitProject creates an example goreleaser.yml in the current directory
func InitProject(filename string) error {
	if _, err := os.Stat(filename); !os.IsNotExist(err) {
		if err != nil {
			return err
		}
		return fmt.Errorf("%s already exists", filename)
	}

	var ctx = context.New(config.Project{})
	var pipe = defaults.Pipe{}
	if err := pipe.Run(ctx); err != nil {
		return err
	}
	out, err := yaml.Marshal(ctx.Config)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(filename, out, 0644)
}
<commit_msg>warn when default goreleaser.yml file wasnt loaded<commit_after>package goreleaserlib

import (
	"io/ioutil"
	"log"
	"os"

	yaml "gopkg.in/yaml.v1"

	"fmt"

	"github.com/goreleaser/goreleaser/config"
	"github.com/goreleaser/goreleaser/context"
	"github.com/goreleaser/goreleaser/pipeline"
	"github.com/goreleaser/goreleaser/pipeline/archive"
	"github.com/goreleaser/goreleaser/pipeline/brew"
	"github.com/goreleaser/goreleaser/pipeline/build"
	"github.com/goreleaser/goreleaser/pipeline/checksums"
	"github.com/goreleaser/goreleaser/pipeline/defaults"
	"github.com/goreleaser/goreleaser/pipeline/env"
	"github.com/goreleaser/goreleaser/pipeline/fpm"
	"github.com/goreleaser/goreleaser/pipeline/git"
	"github.com/goreleaser/goreleaser/pipeline/release"
)

var pipes = []pipeline.Pipe{
	defaults.Pipe{},  // load default configs
	git.Pipe{},       // get and validate git repo state
	env.Pipe{},       // load and validate environment variables
	build.Pipe{},     // build
	archive.Pipe{},   // archive (tar.gz, zip, etc)
	fpm.Pipe{},       // archive via fpm (deb, rpm, etc)
	checksums.Pipe{}, // checksums of the files
	release.Pipe{},   // release to github
	brew.Pipe{},      // push to brew tap
}

func init() {
	log.SetFlags(0)
}

// Flags interface represents an extractor of cli flags
type Flags interface {
	IsSet(s string) bool
	String(s string) string
	Bool(s string) bool
}

// Release runs the release process with the given flags
func Release(flags Flags) error {
	var file = flags.String("config")
	var notes = flags.String("release-notes")
	cfg, err := config.Load(file)
	if err != nil {
		// Allow file not found errors if config file was not
		// explicitly specified
		_, statErr := os.Stat(file)
		if !os.IsNotExist(statErr) || flags.IsSet("config") {
			return err
		}
		log.Printf("WARNING: Could not load %v\n", file)
	}
	var ctx = context.New(cfg)
	ctx.Validate = !flags.Bool("skip-validate")
	ctx.Publish = !flags.Bool("skip-publish")
	if notes != "" {
		bts, err := ioutil.ReadFile(notes)
		if err != nil {
			return err
		}
		log.Println("Loaded custom release notes from", notes)
		ctx.ReleaseNotes = string(bts)
	}
	ctx.Snapshot = flags.Bool("snapshot")
	if ctx.Snapshot {
		log.Println("Publishing disabled in snapshot mode")
		ctx.Publish = false
	}
	for _, pipe := range pipes {
		log.Println(pipe.Description())
		log.SetPrefix(" -> ")
		if err := pipe.Run(ctx); err != nil {
			return err
		}
		log.SetPrefix("")
	}
	log.Println("Done!")
	return nil
}

// InitProject creates an example goreleaser.yml in the current directory
func InitProject(filename string) error {
	if _, err := os.Stat(filename); !os.IsNotExist(err) {
		if err != nil {
			return err
		}
		return fmt.Errorf("%s already exists", filename)
	}

	var ctx = context.New(config.Project{})
	var pipe = defaults.Pipe{}
	if err := pipe.Run(ctx); err != nil {
		return err
	}
	out, err := yaml.Marshal(ctx.Config)
	if err != nil {
		return err
	}

	return ioutil.WriteFile(filename, out, 0644)
}
<|endoftext|>


<commit_before>package gorillamux

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"reflect"

	"github.com/domonda/errors"
	"github.com/h2non/filetype"
	"github.com/h2non/filetype/types"

	command "github.com/ungerik/go-command"
)

type ResultsWriter interface {
	WriteResults(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error
}

type ResultsWriterFunc func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error

func (f ResultsWriterFunc) WriteResults(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	return f(args, vars, resultVals, resultErr, writer, request)
}

func encodeJSON(response interface{}) ([]byte, error) {
	if PrettyPrint {
		return json.MarshalIndent(response, "", PrettyPrintIndent)
	}
	return json.Marshal(response)
}

var RespondJSON ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf []byte
	for _, resultVal := range resultVals {
		b, err := encodeJSON(resultVal.Interface())
		if err != nil {
			return err
		}
		buf = append(buf, b...)
	}
	writer.Header().Set("Content-Type", "application/json; charset=utf-8")
	writer.Write(buf)
	return nil
}

// RespondBinary responds with contentType using the binary data from results of type []byte, string, or io.Reader.
func RespondBinary(contentType string) ResultsWriterFunc {
	return func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) (err error) {
		if resultErr != nil {
			return resultErr
		}
		var buf bytes.Buffer
		for _, resultVal := range resultVals {
			switch data := resultVal.Interface().(type) {
			case []byte:
				_, err = buf.Write(data)
			case string:
				_, err = buf.WriteString(data)
			case io.Reader:
				_, err = io.Copy(&buf, data)
			default:
				return errors.Errorf("RespondBinary does not support result type %s", resultVal.Type())
			}
			if err != nil {
				return err
			}
		}
		writer.Header().Set("Content-Type", contentType)
		writer.Write(buf.Bytes())
		return nil
	}
}

func RespondJSONField(fieldName string) ResultsWriterFunc {
	return func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) (err error) {
		if resultErr != nil {
			return resultErr
		}
		var buf []byte
		m := make(map[string]interface{})
		if len(resultVals) > 0 {
			m[fieldName] = resultVals[0].Interface()
		}
		buf, err = encodeJSON(m)
		if err != nil {
			return err
		}
		writer.Header().Set("Content-Type", "application/json; charset=utf-8")
		writer.Write(buf)
		return nil
	}
}

func encodeXML(response interface{}) ([]byte, error) {
	if PrettyPrint {
		return xml.MarshalIndent(response, "", PrettyPrintIndent)
	}
	return xml.Marshal(response)
}

var RespondXML ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf []byte
	for _, resultVal := range resultVals {
		b, err := encodeXML(resultVal.Interface())
		if err != nil {
			return err
		}
		buf = append(buf, b...)
	}
	writer.Header().Set("Content-Type", "application/xml; charset=utf-8")
	writer.Write(buf)
	return nil
}

var RespondPlaintext ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf bytes.Buffer
	for _, resultVal := range resultVals {
		result := resultVal.Interface()
		if b, ok := result.([]byte); ok {
			buf.Write(b)
		} else {
			fmt.Fprintf(&buf, "%s", result)
		}
	}
	writer.Header().Add("Content-Type", "text/plain; charset=utf-8")
	writer.Write(buf.Bytes())
	return nil
}

var RespondHTML ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf bytes.Buffer
	for _, resultVal := range resultVals {
		result := resultVal.Interface()
		if b, ok := result.([]byte); ok {
			buf.Write(b)
		} else {
			fmt.Fprintf(&buf, "%s", result)
		}
	}
	writer.Header().Add("Content-Type", "text/html; charset=utf-8")
	writer.Write(buf.Bytes())
	return nil
}

var RespondDetectContentType ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	if len(resultVals) != 1 {
		return errors.Errorf("RespondDetectContentType needs 1 result, got %d", len(resultVals))
	}
	data, ok := resultVals[0].Interface().([]byte)
	if !ok {
		return errors.Errorf("RespondDetectContentType needs []byte result, got %T", resultVals[0].Interface())
	}

	writer.Header().Add("Content-Type", DetectContentType(data))
	writer.Write(data)
	return nil
}

var RespondNothing ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	return resultErr
}

// DetectContentType tries to detect the MIME content-type of data,
// or returns "application/octet-stream" if none could be identified.
func DetectContentType(data []byte) string {
	kind, _ := filetype.Match(data)
	if kind == types.Unknown {
		return "application/octet-stream"
	}
	return kind.MIME.Value
}
<commit_msg>use http.DetectContentType as backup for github.com/h2non/filetype<commit_after>package gorillamux

import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"reflect"

	"github.com/domonda/errors"
	"github.com/h2non/filetype"
	"github.com/h2non/filetype/types"

	command "github.com/ungerik/go-command"
)

type ResultsWriter interface {
	WriteResults(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error
}

type ResultsWriterFunc func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error

func (f ResultsWriterFunc) WriteResults(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	return f(args, vars, resultVals, resultErr, writer, request)
}

func encodeJSON(response interface{}) ([]byte, error) {
	if PrettyPrint {
		return json.MarshalIndent(response, "", PrettyPrintIndent)
	}
	return json.Marshal(response)
}

var RespondJSON ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf []byte
	for _, resultVal := range resultVals {
		b, err := encodeJSON(resultVal.Interface())
		if err != nil {
			return err
		}
		buf = append(buf, b...)
	}
	writer.Header().Set("Content-Type", "application/json; charset=utf-8")
	writer.Write(buf)
	return nil
}

// RespondBinary responds with contentType using the binary data from results of type []byte, string, or io.Reader.
func RespondBinary(contentType string) ResultsWriterFunc {
	return func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) (err error) {
		if resultErr != nil {
			return resultErr
		}
		var buf bytes.Buffer
		for _, resultVal := range resultVals {
			switch data := resultVal.Interface().(type) {
			case []byte:
				_, err = buf.Write(data)
			case string:
				_, err = buf.WriteString(data)
			case io.Reader:
				_, err = io.Copy(&buf, data)
			default:
				return errors.Errorf("RespondBinary does not support result type %s", resultVal.Type())
			}
			if err != nil {
				return err
			}
		}
		writer.Header().Set("Content-Type", contentType)
		writer.Write(buf.Bytes())
		return nil
	}
}

func RespondJSONField(fieldName string) ResultsWriterFunc {
	return func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) (err error) {
		if resultErr != nil {
			return resultErr
		}
		var buf []byte
		m := make(map[string]interface{})
		if len(resultVals) > 0 {
			m[fieldName] = resultVals[0].Interface()
		}
		buf, err = encodeJSON(m)
		if err != nil {
			return err
		}
		writer.Header().Set("Content-Type", "application/json; charset=utf-8")
		writer.Write(buf)
		return nil
	}
}

func encodeXML(response interface{}) ([]byte, error) {
	if PrettyPrint {
		return xml.MarshalIndent(response, "", PrettyPrintIndent)
	}
	return xml.Marshal(response)
}

var RespondXML ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf []byte
	for _, resultVal := range resultVals {
		b, err := encodeXML(resultVal.Interface())
		if err != nil {
			return err
		}
		buf = append(buf, b...)
	}
	writer.Header().Set("Content-Type", "application/xml; charset=utf-8")
	writer.Write(buf)
	return nil
}

var RespondPlaintext ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf bytes.Buffer
	for _, resultVal := range resultVals {
		result := resultVal.Interface()
		if b, ok := result.([]byte); ok {
			buf.Write(b)
		} else {
			fmt.Fprintf(&buf, "%s", result)
		}
	}
	writer.Header().Add("Content-Type", "text/plain; charset=utf-8")
	writer.Write(buf.Bytes())
	return nil
}

var RespondHTML ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	var buf bytes.Buffer
	for _, resultVal := range resultVals {
		result := resultVal.Interface()
		if b, ok := result.([]byte); ok {
			buf.Write(b)
		} else {
			fmt.Fprintf(&buf, "%s", result)
		}
	}
	writer.Header().Add("Content-Type", "text/html; charset=utf-8")
	writer.Write(buf.Bytes())
	return nil
}

var RespondDetectContentType ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	if resultErr != nil {
		return resultErr
	}
	if len(resultVals) != 1 {
		return errors.Errorf("RespondDetectContentType needs 1 result, got %d", len(resultVals))
	}
	data, ok := resultVals[0].Interface().([]byte)
	if !ok {
		return errors.Errorf("RespondDetectContentType needs []byte result, got %T", resultVals[0].Interface())
	}

	writer.Header().Add("Content-Type", DetectContentType(data))
	writer.Write(data)
	return nil
}

var RespondNothing ResultsWriterFunc = func(args command.Args, vars map[string]string, resultVals []reflect.Value, resultErr error, writer http.ResponseWriter, request *http.Request) error {
	return resultErr
}

// DetectContentType tries to detect the MIME content-type of data,
// or returns "application/octet-stream" if none could be identified.
func DetectContentType(data []byte) string {
	kind, _ := filetype.Match(data)
	if kind == types.Unknown {
		return http.DetectContentType(data)
	}
	return kind.MIME.Value
}
<|endoftext|>