<commit_before>// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

// Package les implements the Light Ethereum Subprotocol.
package les

import (
	"errors"
	"fmt"
	"time"

	"github.com/ethereum/ethash"
	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/compiler"
	"github.com/ethereum/go-ethereum/common/httpclient"
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/core/vm"
	"github.com/ethereum/go-ethereum/eth"
	"github.com/ethereum/go-ethereum/eth/downloader"
	"github.com/ethereum/go-ethereum/eth/filters"
	"github.com/ethereum/go-ethereum/eth/gasprice"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/internal/ethapi"
	"github.com/ethereum/go-ethereum/light"
	"github.com/ethereum/go-ethereum/node"
	"github.com/ethereum/go-ethereum/p2p"
	rpc "github.com/ethereum/go-ethereum/rpc"
)

type LightEthereum struct {
	odr         *LesOdr
	relay       *LesTxRelay
	chainConfig *core.ChainConfig
	// Channel for shutting down the service
	shutdownChan chan bool
	// Handlers
	txPool          *light.TxPool
	blockchain      *light.LightChain
	protocolManager *ProtocolManager
	// DB interfaces
	chainDb ethdb.Database // Block chain database

	ApiBackend *LesApiBackend

	eventMux       *event.TypeMux
	pow            *ethash.Ethash
	httpclient     *httpclient.HTTPClient
	accountManager *accounts.Manager
	solcPath       string
	solc           *compiler.Solidity

	NatSpec       bool
	PowTest       bool
	netVersionId  int
	netRPCService *ethapi.PublicNetAPI
}

func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
	chainDb, err := eth.CreateDB(ctx, config, "lightchaindata")
	if err != nil {
		return nil, err
	}
	if err := eth.SetupGenesisBlock(&chainDb, config); err != nil {
		return nil, err
	}
	pow, err := eth.CreatePoW(config)
	if err != nil {
		return nil, err
	}

	odr := NewLesOdr(chainDb)
	relay := NewLesTxRelay()
	eth := &LightEthereum{
		odr:            odr,
		relay:          relay,
		chainDb:        chainDb,
		eventMux:       ctx.EventMux,
		accountManager: ctx.AccountManager,
		pow:            pow,
		shutdownChan:   make(chan bool),
		httpclient:     httpclient.New(config.DocRoot),
		netVersionId:   config.NetworkId,
		NatSpec:        config.NatSpec,
		PowTest:        config.PowTest,
		solcPath:       config.SolcPath,
	}

	if config.ChainConfig == nil {
		return nil, errors.New("missing chain config")
	}
	eth.chainConfig = config.ChainConfig
	eth.chainConfig.VmConfig = vm.Config{
		EnableJit: config.EnableJit,
		ForceJit:  config.ForceJit,
	}
	eth.blockchain, err = light.NewLightChain(odr, eth.chainConfig, eth.pow, eth.eventMux)
	if err != nil {
		if err == core.ErrNoGenesis {
			return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`)
		}
		return nil, err
	}

	eth.txPool = light.NewTxPool(eth.chainConfig, eth.eventMux, eth.blockchain, eth.relay)
	if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.LightMode, config.NetworkId, eth.eventMux, eth.pow, eth.blockchain, nil, chainDb, odr, relay); err != nil {
		return nil, err
	}

	eth.ApiBackend = &LesApiBackend{eth, nil}
	eth.ApiBackend.gpo = gasprice.NewLightPriceOracle(eth.ApiBackend)
	return eth, nil
}

type LightDummyAPI struct{}

// Etherbase is the address that mining rewards will be send to
func (s *LightDummyAPI) Etherbase() (common.Address, error) {
	return common.Address{}, fmt.Errorf("not supported")
}

// Coinbase is the address that mining rewards will be send to (alias for Etherbase)
func (s *LightDummyAPI) Coinbase() (common.Address, error) {
	return common.Address{}, fmt.Errorf("not supported")
}

// Hashrate returns the POW hashrate
func (s *LightDummyAPI) Hashrate() *rpc.HexNumber {
	return rpc.NewHexNumber(0)
}

// Mining returns an indication if this node is currently mining.
func (s *LightDummyAPI) Mining() bool {
	return false
}

// APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func (s *LightEthereum) APIs() []rpc.API {
	return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{
		{
			Namespace: "eth",
			Version:   "1.0",
			Service:   &LightDummyAPI{},
			Public:    true,
		}, {
			Namespace: "eth",
			Version:   "1.0",
			Service:   downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux),
			Public:    true,
		}, {
			Namespace: "eth",
			Version:   "1.0",
			Service:   filters.NewPublicFilterAPI(s.ApiBackend, true),
			Public:    true,
		}, {
			Namespace: "net",
			Version:   "1.0",
			Service:   s.netRPCService,
			Public:    true,
		},
	}...)
}

func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) {
	s.blockchain.ResetWithGenesisBlock(gb)
}

func (s *LightEthereum) BlockChain() *light.LightChain      { return s.blockchain }
func (s *LightEthereum) TxPool() *light.TxPool              { return s.txPool }
func (s *LightEthereum) LesVersion() int                    { return int(s.protocolManager.SubProtocols[0].Version) }
func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }

// Protocols implements node.Service, returning all the currently configured
// network protocols to start.
func (s *LightEthereum) Protocols() []p2p.Protocol {
	return s.protocolManager.SubProtocols
}

// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
func (s *LightEthereum) Start(srvr *p2p.Server) error {
	s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.netVersionId)
	s.protocolManager.Start(srvr)
	return nil
}

// Stop implements node.Service, terminating all internal goroutines used by the
// Ethereum protocol.
func (s *LightEthereum) Stop() error {
	s.odr.Stop()
	s.blockchain.Stop()
	s.protocolManager.Stop()
	s.txPool.Stop()

	s.eventMux.Stop()

	time.Sleep(time.Millisecond * 200)
	s.chainDb.Close()
	close(s.shutdownChan)

	return nil
}
<commit_msg>les: print 'experimental feature' warning on startup<commit_after>// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

// Package les implements the Light Ethereum Subprotocol.
package les

import (
	"errors"
	"fmt"
	"time"

	"github.com/ethereum/ethash"
	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/compiler"
	"github.com/ethereum/go-ethereum/common/httpclient"
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/core/vm"
	"github.com/ethereum/go-ethereum/eth"
	"github.com/ethereum/go-ethereum/eth/downloader"
	"github.com/ethereum/go-ethereum/eth/filters"
	"github.com/ethereum/go-ethereum/eth/gasprice"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/event"
	"github.com/ethereum/go-ethereum/internal/ethapi"
	"github.com/ethereum/go-ethereum/light"
	"github.com/ethereum/go-ethereum/logger"
	"github.com/ethereum/go-ethereum/logger/glog"
	"github.com/ethereum/go-ethereum/node"
	"github.com/ethereum/go-ethereum/p2p"
	rpc "github.com/ethereum/go-ethereum/rpc"
)

type LightEthereum struct {
	odr         *LesOdr
	relay       *LesTxRelay
	chainConfig *core.ChainConfig
	// Channel for shutting down the service
	shutdownChan chan bool
	// Handlers
	txPool          *light.TxPool
	blockchain      *light.LightChain
	protocolManager *ProtocolManager
	// DB interfaces
	chainDb ethdb.Database // Block chain database

	ApiBackend *LesApiBackend

	eventMux       *event.TypeMux
	pow            *ethash.Ethash
	httpclient     *httpclient.HTTPClient
	accountManager *accounts.Manager
	solcPath       string
	solc           *compiler.Solidity

	NatSpec       bool
	PowTest       bool
	netVersionId  int
	netRPCService *ethapi.PublicNetAPI
}

func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
	chainDb, err := eth.CreateDB(ctx, config, "lightchaindata")
	if err != nil {
		return nil, err
	}
	if err := eth.SetupGenesisBlock(&chainDb, config); err != nil {
		return nil, err
	}
	pow, err := eth.CreatePoW(config)
	if err != nil {
		return nil, err
	}

	odr := NewLesOdr(chainDb)
	relay := NewLesTxRelay()
	eth := &LightEthereum{
		odr:            odr,
		relay:          relay,
		chainDb:        chainDb,
		eventMux:       ctx.EventMux,
		accountManager: ctx.AccountManager,
		pow:            pow,
		shutdownChan:   make(chan bool),
		httpclient:     httpclient.New(config.DocRoot),
		netVersionId:   config.NetworkId,
		NatSpec:        config.NatSpec,
		PowTest:        config.PowTest,
		solcPath:       config.SolcPath,
	}

	if config.ChainConfig == nil {
		return nil, errors.New("missing chain config")
	}
	eth.chainConfig = config.ChainConfig
	eth.chainConfig.VmConfig = vm.Config{
		EnableJit: config.EnableJit,
		ForceJit:  config.ForceJit,
	}
	eth.blockchain, err = light.NewLightChain(odr, eth.chainConfig, eth.pow, eth.eventMux)
	if err != nil {
		if err == core.ErrNoGenesis {
			return nil, fmt.Errorf(`Genesis block not found. Please supply a genesis block with the "--genesis /path/to/file" argument`)
		}
		return nil, err
	}

	eth.txPool = light.NewTxPool(eth.chainConfig, eth.eventMux, eth.blockchain, eth.relay)
	if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.LightMode, config.NetworkId, eth.eventMux, eth.pow, eth.blockchain, nil, chainDb, odr, relay); err != nil {
		return nil, err
	}

	eth.ApiBackend = &LesApiBackend{eth, nil}
	eth.ApiBackend.gpo = gasprice.NewLightPriceOracle(eth.ApiBackend)
	return eth, nil
}

type LightDummyAPI struct{}

// Etherbase is the address that mining rewards will be send to
func (s *LightDummyAPI) Etherbase() (common.Address, error) {
	return common.Address{}, fmt.Errorf("not supported")
}

// Coinbase is the address that mining rewards will be send to (alias for Etherbase)
func (s *LightDummyAPI) Coinbase() (common.Address, error) {
	return common.Address{}, fmt.Errorf("not supported")
}

// Hashrate returns the POW hashrate
func (s *LightDummyAPI) Hashrate() *rpc.HexNumber {
	return rpc.NewHexNumber(0)
}

// Mining returns an indication if this node is currently mining.
func (s *LightDummyAPI) Mining() bool {
	return false
}

// APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func (s *LightEthereum) APIs() []rpc.API {
	return append(ethapi.GetAPIs(s.ApiBackend, s.solcPath), []rpc.API{
		{
			Namespace: "eth",
			Version:   "1.0",
			Service:   &LightDummyAPI{},
			Public:    true,
		}, {
			Namespace: "eth",
			Version:   "1.0",
			Service:   downloader.NewPublicDownloaderAPI(s.protocolManager.downloader, s.eventMux),
			Public:    true,
		}, {
			Namespace: "eth",
			Version:   "1.0",
			Service:   filters.NewPublicFilterAPI(s.ApiBackend, true),
			Public:    true,
		}, {
			Namespace: "net",
			Version:   "1.0",
			Service:   s.netRPCService,
			Public:    true,
		},
	}...)
}

func (s *LightEthereum) ResetWithGenesisBlock(gb *types.Block) {
	s.blockchain.ResetWithGenesisBlock(gb)
}

func (s *LightEthereum) BlockChain() *light.LightChain      { return s.blockchain }
func (s *LightEthereum) TxPool() *light.TxPool              { return s.txPool }
func (s *LightEthereum) LesVersion() int                    { return int(s.protocolManager.SubProtocols[0].Version) }
func (s *LightEthereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }

// Protocols implements node.Service, returning all the currently configured
// network protocols to start.
func (s *LightEthereum) Protocols() []p2p.Protocol {
	return s.protocolManager.SubProtocols
}

// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
func (s *LightEthereum) Start(srvr *p2p.Server) error {
	glog.V(logger.Info).Infof("WARNING: light client mode is an experimental feature")
	s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.netVersionId)
	s.protocolManager.Start(srvr)
	return nil
}

// Stop implements node.Service, terminating all internal goroutines used by the
// Ethereum protocol.
func (s *LightEthereum) Stop() error {
	s.odr.Stop()
	s.blockchain.Stop()
	s.protocolManager.Stop()
	s.txPool.Stop()

	s.eventMux.Stop()

	time.Sleep(time.Millisecond * 200)
	s.chainDb.Close()
	close(s.shutdownChan)

	return nil
}
<|endoftext|>


<commit_before>package g

import (
	"strings"

	. "github.com/alecthomas/chroma" // nolint
	"github.com/alecthomas/chroma/lexers/h"
	"github.com/alecthomas/chroma/lexers/internal"
)

// Go lexer.
var Go = internal.Register(MustNewLexer(
	&Config{
		Name:      "Go",
		Aliases:   []string{"go", "golang"},
		Filenames: []string{"*.go"},
		MimeTypes: []string{"text/x-gosrc"},
	},
	Rules{
		"root": {
			{`\n`, Text, nil},
			{`\s+`, Text, nil},
			{`\\\n`, Text, nil},
			{`//(.*?)\n`, CommentSingle, nil},
			{`/(\\\n)?[*](.|\n)*?[*](\\\n)?/`, CommentMultiline, nil},
			{`(import|package)\b`, KeywordNamespace, nil},
			{`(var|func|struct|map|chan|type|interface|const)\b`, KeywordDeclaration, nil},
			{Words(``, `\b`, `break`, `default`, `select`, `case`, `defer`, `go`, `else`, `goto`, `switch`, `fallthrough`, `if`, `range`, `continue`, `for`, `return`), Keyword, nil},
			{`(true|false|iota|nil)\b`, KeywordConstant, nil},
			{Words(``, `\b(\()`, `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `int`, `int8`, `int16`, `int32`, `int64`, `float`, `float32`, `float64`, `complex64`, `complex128`, `byte`, `rune`, `string`, `bool`, `error`, `uintptr`, `print`, `println`, `panic`, `recover`, `close`, `complex`, `real`, `imag`, `len`, `cap`, `append`, `copy`, `delete`, `new`, `make`), ByGroups(NameBuiltin, Punctuation), nil},
			{Words(``, `\b`, `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `int`, `int8`, `int16`, `int32`, `int64`, `float`, `float32`, `float64`, `complex64`, `complex128`, `byte`, `rune`, `string`, `bool`, `error`, `uintptr`), KeywordType, nil},
			{`\d+i`, LiteralNumber, nil},
			{`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil},
			{`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil},
			{`\d+[Ee][-+]\d+i`, LiteralNumber, nil},
			{`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
			{`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
			{`0[0-7]+`, LiteralNumberOct, nil},
			{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
			{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
			{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
			{"(`)([^`]*)(`)", ByGroups(LiteralString, Using(TypeRemappingLexer(GoTextTemplate, TypeMapping{{Other, LiteralString, nil}})), LiteralString), nil},
			{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
			{`(<<=|>>=|<<|>>|<=|>=|&\^=|&\^|\+=|-=|\*=|/=|%=|&=|\|=|&&|\|\||<-|\+\+|--|==|!=|:=|\.\.\.|[+\-*/%&])`, Operator, nil},
			{`[|^<>=!()\[\]{}.,;:]`, Punctuation, nil},
			{`[^\W\d]\w*`, NameOther, nil},
		},
	},
).SetAnalyser(func(text string) float32 {
	if strings.Contains(text, "fmt.") && strings.Contains(text, "package ") {
		return 0.5
	}
	if strings.Contains(text, "package ") {
		return 0.1
	}
	return 0.0
}))

var goTemplateRules = Rules{
	"root": {
		{`{{[-]?`, CommentPreproc, Push("template")},
		{`[^{]+`, Other, nil},
		{`{`, Other, nil},
	},
	"template": {
		{`[-]?}}`, CommentPreproc, Pop(1)},
		{`\s+`, Whitespace, nil},
		{`/\*.*?\*/`, Comment, nil},
		{`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline
		{`\(`, Operator, Push("subexpression")},
		{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
		Include("expression"),
	},
	"subexpression": {
		{`\)`, Operator, Pop(1)},
		Include("expression"),
	},
	"expression": {
		{`\(`, Operator, Push("subexpression")},
		{`(if|while|with|template|end|true|false|nil|and|call|html|index|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|le|gt|ge)\b`, Keyword, nil},
		{`\|`, Operator, nil},
		{`[^\W\d]\w*`, NameOther, nil},
		{`\.(?:[^\W\d]\w*)?`, NameAttribute, nil},
		{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
		{`\d+i`, LiteralNumber, nil},
		{`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil},
		{`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil},
		{`\d+[Ee][-+]\d+i`, LiteralNumber, nil},
		{`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
		{`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
		{`0[0-7]+`, LiteralNumberOct, nil},
		{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
		{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
		{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
		{"`[^`]*`", LiteralString, nil},
	},
}

var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
	&Config{
		Name:    "Go HTML Template",
		Aliases: []string{"go-html-template"},
	},
	goTemplateRules,
)))

var GoTextTemplate = internal.Register(MustNewLexer(
	&Config{
		Name:    "Go Text Template",
		Aliases: []string{"go-text-template"},
	},
	goTemplateRules,
))
<commit_msg>Correctly handle := and $<commit_after>package g

import (
	"strings"

	. "github.com/alecthomas/chroma" // nolint
	"github.com/alecthomas/chroma/lexers/h"
	"github.com/alecthomas/chroma/lexers/internal"
)

// Go lexer.
var Go = internal.Register(MustNewLexer(
	&Config{
		Name:      "Go",
		Aliases:   []string{"go", "golang"},
		Filenames: []string{"*.go"},
		MimeTypes: []string{"text/x-gosrc"},
	},
	Rules{
		"root": {
			{`\n`, Text, nil},
			{`\s+`, Text, nil},
			{`\\\n`, Text, nil},
			{`//(.*?)\n`, CommentSingle, nil},
			{`/(\\\n)?[*](.|\n)*?[*](\\\n)?/`, CommentMultiline, nil},
			{`(import|package)\b`, KeywordNamespace, nil},
			{`(var|func|struct|map|chan|type|interface|const)\b`, KeywordDeclaration, nil},
			{Words(``, `\b`, `break`, `default`, `select`, `case`, `defer`, `go`, `else`, `goto`, `switch`, `fallthrough`, `if`, `range`, `continue`, `for`, `return`), Keyword, nil},
			{`(true|false|iota|nil)\b`, KeywordConstant, nil},
			{Words(``, `\b(\()`, `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `int`, `int8`, `int16`, `int32`, `int64`, `float`, `float32`, `float64`, `complex64`, `complex128`, `byte`, `rune`, `string`, `bool`, `error`, `uintptr`, `print`, `println`, `panic`, `recover`, `close`, `complex`, `real`, `imag`, `len`, `cap`, `append`, `copy`, `delete`, `new`, `make`), ByGroups(NameBuiltin, Punctuation), nil},
			{Words(``, `\b`, `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `int`, `int8`, `int16`, `int32`, `int64`, `float`, `float32`, `float64`, `complex64`, `complex128`, `byte`, `rune`, `string`, `bool`, `error`, `uintptr`), KeywordType, nil},
			{`\d+i`, LiteralNumber, nil},
			{`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil},
			{`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil},
			{`\d+[Ee][-+]\d+i`, LiteralNumber, nil},
			{`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
			{`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
			{`0[0-7]+`, LiteralNumberOct, nil},
			{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
			{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
			{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
			{"(`)([^`]*)(`)", ByGroups(LiteralString, Using(TypeRemappingLexer(GoTextTemplate, TypeMapping{{Other, LiteralString, nil}})), LiteralString), nil},
			{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
			{`(<<=|>>=|<<|>>|<=|>=|&\^=|&\^|\+=|-=|\*=|/=|%=|&=|\|=|&&|\|\||<-|\+\+|--|==|!=|:=|\.\.\.|[+\-*/%&])`, Operator, nil},
			{`[|^<>=!()\[\]{}.,;:]`, Punctuation, nil},
			{`[^\W\d]\w*`, NameOther, nil},
		},
	},
).SetAnalyser(func(text string) float32 {
	if strings.Contains(text, "fmt.") && strings.Contains(text, "package ") {
		return 0.5
	}
	if strings.Contains(text, "package ") {
		return 0.1
	}
	return 0.0
}))

var goTemplateRules = Rules{
	"root": {
		{`{{[-]?`, CommentPreproc, Push("template")},
		{`[^{]+`, Other, nil},
		{`{`, Other, nil},
	},
	"template": {
		{`[-]?}}`, CommentPreproc, Pop(1)},
		{`\s+`, Whitespace, nil},
		{`/\*.*?\*/`, Comment, nil},
		{`(?=}})`, CommentPreproc, Pop(1)}, // Terminate the pipeline
		{`\(`, Operator, Push("subexpression")},
		{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
		Include("expression"),
	},
	"subexpression": {
		{`\)`, Operator, Pop(1)},
		Include("expression"),
	},
	"expression": {
		{`\(`, Operator, Push("subexpression")},
		{`(range|if|else|while|with|template|end|true|false|nil|and|call|html|index|js|len|not|or|print|printf|println|urlquery|eq|ne|lt|le|gt|ge)\b`, Keyword, nil},
		{`\||:=`, Operator, nil},
		{`[$]?[^\W\d]\w*`, NameOther, nil},
		{`[$]?\.(?:[^\W\d]\w*)?`, NameAttribute, nil},
		{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
		{`\d+i`, LiteralNumber, nil},
		{`\d+\.\d*([Ee][-+]\d+)?i`, LiteralNumber, nil},
		{`\.\d+([Ee][-+]\d+)?i`, LiteralNumber, nil},
		{`\d+[Ee][-+]\d+i`, LiteralNumber, nil},
		{`\d+(\.\d+[eE][+\-]?\d+|\.\d*|[eE][+\-]?\d+)`, LiteralNumberFloat, nil},
		{`\.\d+([eE][+\-]?\d+)?`, LiteralNumberFloat, nil},
		{`0[0-7]+`, LiteralNumberOct, nil},
		{`0[xX][0-9a-fA-F]+`, LiteralNumberHex, nil},
		{`(0|[1-9][0-9]*)`, LiteralNumberInteger, nil},
		{`'(\\['"\\abfnrtv]|\\x[0-9a-fA-F]{2}|\\[0-7]{1,3}|\\u[0-9a-fA-F]{4}|\\U[0-9a-fA-F]{8}|[^\\])'`, LiteralStringChar, nil},
		{"`[^`]*`", LiteralString, nil},
	},
}

var GoHTMLTemplate = internal.Register(DelegatingLexer(h.HTML, MustNewLexer(
	&Config{
		Name:    "Go HTML Template",
		Aliases: []string{"go-html-template"},
	},
	goTemplateRules,
)))

var GoTextTemplate = internal.Register(MustNewLexer(
	&Config{
		Name:    "Go Text Template",
		Aliases: []string{"go-text-template"},
	},
	goTemplateRules,
))
<|endoftext|>


<commit_before>package gen

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"code.google.com/p/go.crypto/bcrypt"
	"regexp"
)

func UnusedUsername(db *sql.DB, username string) bool {
	// Always prepare queries to be used multiple times. The parameter placehold is ?
	stmt, err := db.Prepare(`
	SELECT users.name
		FROM users
		WHERE users.name = ?
		`)

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 19`)
	}
	defer stmt.Close()

	// db.Query() prepares, executes, and closes a prepared statement - three round
	// trips to the databse. Call it infrequently as possible; use efficient SQL statments
	rows, err := stmt.Query(username)
	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 27`)
	}
	// Always defer rows.Close(), even if you explicitly Close it at the end of the
	// loop. The connection will have the chance to remain open otherwise.
	defer rows.Close()

	// The last rows.Next() call will encounter an EOF error and call rows.Close()
	for rows.Next() {
		return true
	}
	return false
}

func UnusedEmail(db *sql.DB, email string) bool {
	stmt, err := db.Prepare(`
	SELECT users.name
		FROM users
		WHERE users.email = ?
		`)

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 19`)
	}
	defer stmt.Close()

	// db.Query() prepares, executes, and closes a prepared statement - three round
	// trips to the databse. Call it infrequently as possible; use efficient SQL statments
	rows, err := stmt.Query(email)
	if err != nil {
		panic(err.Error() + ` ERROR IN UNUSED EMAIL`)
	}
	// Always defer rows.Close(), even if you explicitly Close it at the end of the
	// loop. The connection will have the chance to remain open otherwise.
	defer rows.Close()

	// The last rows.Next() call will encounter an EOF error and call rows.Close()
	for rows.Next() {
		return true
	}
	return false
}

func InvalidUsername(username string) bool {
	valid, err := regexp.Match("^[a-zA-Z0-9_-]{6,20}$", []byte(username))
	if err!= nil {
		panic(err.Error() + ` Error in the regexp checking username`)
	}
	if valid {
		return false
	}
	return true
}

func hashPassword (password string) []byte{
	hashed, err := bcrypt.GenerateFromPassword([]byte(password), 10)
	if err != nil{
		panic(err.Error() + ` THE ERROR IS ON LINE 43`)
	}
	return hashed
}

func CreateUser(db *sql.DB, username string, password string, email string){
		// Always prepare queries to be used multiple times. The parameter placehold is ?
	stmt, err := db.Prepare(`
		INSERT INTO users (name, email, password, session)
			VALUES (?, ?, ?, ?)
		`)
	defer stmt.Close()

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 56`)
	}
	_, err = stmt.Exec(username, email, hashPassword(password), "123")
	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 60`)
	}
	/*
	rowCnt, err := res.RowsAffected()
	if err != nil {
		// Log the error
	}
	*/
}

func CheckCredentials(db *sql.DB, username string, password string) bool {
	stmt, err := db.Prepare(`
	SELECT users.password
		FROM users
		WHERE users.name = ?
		`)

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 78`)
	}
	defer stmt.Close()

	// db.Query() prepares, executes, and closes a prepared statement - three round
	// trips to the databse. Call it infrequently as possible; use efficient SQL statments
	rows, err := stmt.Query(username)
	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 86`)
	}
	// Always defer rows.Close(), even if you explicitly Close it at the end of the
	// loop. The connection will have the chance to remain open otherwise.
	defer rows.Close()

	// The last rows.Next() call will encounter an EOF error and call rows.Close()

	var hashedPassword []byte;

	for rows.Next() {
		err := rows.Scan(&hashedPassword)
		if err != nil {
			panic(err.Error() + ` THE ERROR IS ON LINE 99`)
		}
	}

	if hashedPassword == nil {
		return false
	}

	err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(password))
	if err != nil {
		return false
	}
	return true
}<commit_msg>Changed minimum username to 3 characters<commit_after>package gen

import (
	"database/sql"
	_ "github.com/go-sql-driver/mysql"
	"code.google.com/p/go.crypto/bcrypt"
	"regexp"
)

func UnusedUsername(db *sql.DB, username string) bool {
	// Always prepare queries to be used multiple times. The parameter placehold is ?
	stmt, err := db.Prepare(`
	SELECT users.name
		FROM users
		WHERE users.name = ?
		`)

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 19`)
	}
	defer stmt.Close()

	// db.Query() prepares, executes, and closes a prepared statement - three round
	// trips to the databse. Call it infrequently as possible; use efficient SQL statments
	rows, err := stmt.Query(username)
	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 27`)
	}
	// Always defer rows.Close(), even if you explicitly Close it at the end of the
	// loop. The connection will have the chance to remain open otherwise.
	defer rows.Close()

	// The last rows.Next() call will encounter an EOF error and call rows.Close()
	for rows.Next() {
		return true
	}
	return false
}

func UnusedEmail(db *sql.DB, email string) bool {
	stmt, err := db.Prepare(`
	SELECT users.name
		FROM users
		WHERE users.email = ?
		`)

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 19`)
	}
	defer stmt.Close()

	// db.Query() prepares, executes, and closes a prepared statement - three round
	// trips to the databse. Call it infrequently as possible; use efficient SQL statments
	rows, err := stmt.Query(email)
	if err != nil {
		panic(err.Error() + ` ERROR IN UNUSED EMAIL`)
	}
	// Always defer rows.Close(), even if you explicitly Close it at the end of the
	// loop. The connection will have the chance to remain open otherwise.
	defer rows.Close()

	// The last rows.Next() call will encounter an EOF error and call rows.Close()
	for rows.Next() {
		return true
	}
	return false
}

func InvalidUsername(username string) bool {
	valid, err := regexp.Match("^[a-zA-Z0-9_-]{3,20}$", []byte(username))
	if err!= nil {
		panic(err.Error() + ` Error in the regexp checking username`)
	}
	if valid {
		return false
	}
	return true
}

func hashPassword (password string) []byte{
	hashed, err := bcrypt.GenerateFromPassword([]byte(password), 10)
	if err != nil{
		panic(err.Error() + ` THE ERROR IS ON LINE 43`)
	}
	return hashed
}

func CreateUser(db *sql.DB, username string, password string, email string){
		// Always prepare queries to be used multiple times. The parameter placehold is ?
	stmt, err := db.Prepare(`
		INSERT INTO users (name, email, password, session)
			VALUES (?, ?, ?, ?)
		`)
	defer stmt.Close()

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 56`)
	}
	_, err = stmt.Exec(username, email, hashPassword(password), "123")
	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 60`)
	}
	/*
	rowCnt, err := res.RowsAffected()
	if err != nil {
		// Log the error
	}
	*/
}

func CheckCredentials(db *sql.DB, username string, password string) bool {
	stmt, err := db.Prepare(`
	SELECT users.password
		FROM users
		WHERE users.name = ?
		`)

	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 78`)
	}
	defer stmt.Close()

	// db.Query() prepares, executes, and closes a prepared statement - three round
	// trips to the databse. Call it infrequently as possible; use efficient SQL statments
	rows, err := stmt.Query(username)
	if err != nil {
		panic(err.Error() + ` THE ERROR IS ON LINE 86`)
	}
	// Always defer rows.Close(), even if you explicitly Close it at the end of the
	// loop. The connection will have the chance to remain open otherwise.
	defer rows.Close()

	// The last rows.Next() call will encounter an EOF error and call rows.Close()

	var hashedPassword []byte;

	for rows.Next() {
		err := rows.Scan(&hashedPassword)
		if err != nil {
			panic(err.Error() + ` THE ERROR IS ON LINE 99`)
		}
	}

	if hashedPassword == nil {
		return false
	}

	err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(password))
	if err != nil {
		return false
	}
	return true
}<|endoftext|>


<commit_before>/*
   Copyright 2014 Outbrain 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 inst

import (
	"github.com/github/orchestrator/go/config"
	"regexp"
	"strings"
)

// ClusterInfo makes for a cluster status/info summary
type ClusterInfo struct {
	ClusterName                            string
	ClusterAlias                           string // Human friendly alias
	ClusterDomain                          string // CNAME/VIP/A-record/whatever of the master of this cluster
	CountInstances                         uint
	HeuristicLag                           int64
	HasAutomatedMasterRecovery             bool
	HasAutomatedIntermediateMasterRecovery bool
}

// ReadRecoveryInfo
func (this *ClusterInfo) ReadRecoveryInfo() {
	this.HasAutomatedMasterRecovery = this.filtersMatchCluster(config.Config.RecoverMasterClusterFilters)
	this.HasAutomatedIntermediateMasterRecovery = this.filtersMatchCluster(config.Config.RecoverIntermediateMasterClusterFilters)
}

// filtersMatchCluster will see whether the given filters match the given cluster details
func (this *ClusterInfo) filtersMatchCluster(filters []string) bool {
	for _, filter := range filters {
		if strings.HasPrefix(filter, "alias=") {
			// Match by exact cluster alias name
			alias := strings.SplitN(filter, "=", 2)[1]
			if alias == this.ClusterAlias {
				return true
			}
		} else if strings.HasPrefix(filter, "alias~=") {
			// Match by cluster alias regex
			aliasPattern := strings.SplitN(filter, "~=", 2)[1]
			if matched, _ := regexp.MatchString(aliasPattern, this.ClusterAlias); matched {
				return true
			}
		} else if filter == "*" {
			return true
		} else if matched, _ := regexp.MatchString(filter, this.ClusterName); matched && filter != "" {
			return true
		}
	}
	return false
}

// ApplyClusterAlias updates the given clusterInfo's ClusterAlias property
func (this *ClusterInfo) ApplyClusterAlias() {
	if this.ClusterAlias != "" && this.ClusterAlias != this.ClusterName {
		// Already has an alias; abort
		return
	}
	// Try out the hard-wired config:
	for pattern := range config.Config.ClusterNameToAlias {
		if matched, _ := regexp.MatchString(pattern, this.ClusterName); matched {
			this.ClusterAlias = config.Config.ClusterNameToAlias[pattern]
		}
	}
}
<commit_msg>better cluster filter match<commit_after>/*
   Copyright 2014 Outbrain 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 inst

import (
	"github.com/github/orchestrator/go/config"
	"regexp"
	"strings"
)

// ClusterInfo makes for a cluster status/info summary
type ClusterInfo struct {
	ClusterName                            string
	ClusterAlias                           string // Human friendly alias
	ClusterDomain                          string // CNAME/VIP/A-record/whatever of the master of this cluster
	CountInstances                         uint
	HeuristicLag                           int64
	HasAutomatedMasterRecovery             bool
	HasAutomatedIntermediateMasterRecovery bool
}

// ReadRecoveryInfo
func (this *ClusterInfo) ReadRecoveryInfo() {
	this.HasAutomatedMasterRecovery = this.filtersMatchCluster(config.Config.RecoverMasterClusterFilters)
	this.HasAutomatedIntermediateMasterRecovery = this.filtersMatchCluster(config.Config.RecoverIntermediateMasterClusterFilters)
}

// filtersMatchCluster will see whether the given filters match the given cluster details
func (this *ClusterInfo) filtersMatchCluster(filters []string) bool {
	for _, filter := range filters {
		if filter == this.ClusterName {
			return true
		}
		if filter == this.ClusterAlias {
			return true
		}
		if strings.HasPrefix(filter, "alias=") {
			// Match by exact cluster alias name
			alias := strings.SplitN(filter, "=", 2)[1]
			if alias == this.ClusterAlias {
				return true
			}
		} else if strings.HasPrefix(filter, "alias~=") {
			// Match by cluster alias regex
			aliasPattern := strings.SplitN(filter, "~=", 2)[1]
			if matched, _ := regexp.MatchString(aliasPattern, this.ClusterAlias); matched {
				return true
			}
		} else if filter == "*" {
			return true
		} else if matched, _ := regexp.MatchString(filter, this.ClusterName); matched && filter != "" {
			return true
		}
	}
	return false
}

// ApplyClusterAlias updates the given clusterInfo's ClusterAlias property
func (this *ClusterInfo) ApplyClusterAlias() {
	if this.ClusterAlias != "" && this.ClusterAlias != this.ClusterName {
		// Already has an alias; abort
		return
	}
	// Try out the hard-wired config:
	for pattern := range config.Config.ClusterNameToAlias {
		if matched, _ := regexp.MatchString(pattern, this.ClusterName); matched {
			this.ClusterAlias = config.Config.ClusterNameToAlias[pattern]
		}
	}
}
<|endoftext|>


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

package service

import (
	"io"
	"net"
	"os"
	"path"
	"time"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
	"github.com/keybase/client/go/updater"
	"github.com/keybase/client/go/updater/sources"
	rpc "github.com/keybase/go-framed-msgpack-rpc"
)

type Service struct {
	libkb.Contextified
	isDaemon      bool
	chdirTo       string
	lockPid       *libkb.LockPIDFile
	ForkType      keybase1.ForkType
	startCh       chan struct{}
	stopCh        chan keybase1.ExitCode
	updateChecker *updater.UpdateChecker
	logForwarder  *logFwd
}

func NewService(g *libkb.GlobalContext, isDaemon bool) *Service {
	return &Service{
		Contextified: libkb.NewContextified(g),
		isDaemon:     isDaemon,
		startCh:      make(chan struct{}),
		stopCh:       make(chan keybase1.ExitCode),
		logForwarder: newLogFwd(),
	}
}

func (d *Service) GetStartChannel() <-chan struct{} {
	return d.startCh
}

func (d *Service) RegisterProtocols(srv *rpc.Server, xp rpc.Transporter, connID libkb.ConnectionID, logReg *logRegister, g *libkb.GlobalContext) error {
	protocols := []rpc.Protocol{
		keybase1.AccountProtocol(NewAccountHandler(xp, g)),
		keybase1.BTCProtocol(NewBTCHandler(xp, g)),
		keybase1.ConfigProtocol(NewConfigHandler(xp, g, d)),
		keybase1.CryptoProtocol(NewCryptoHandler(g)),
		keybase1.CtlProtocol(NewCtlHandler(xp, d, g)),
		keybase1.DebuggingProtocol(NewDebuggingHandler(xp)),
		keybase1.DelegateUiCtlProtocol(NewDelegateUICtlHandler(xp, connID, g)),
		keybase1.DeviceProtocol(NewDeviceHandler(xp, g)),
		keybase1.FavoriteProtocol(NewFavoriteHandler(xp, g)),
		keybase1.IdentifyProtocol(NewIdentifyHandler(xp, g)),
		keybase1.KbfsProtocol(NewKBFSHandler(xp, g)),
		keybase1.LogProtocol(NewLogHandler(xp, logReg, g)),
		keybase1.LoginProtocol(NewLoginHandler(xp, g)),
		keybase1.NotifyCtlProtocol(NewNotifyCtlHandler(xp, connID, g)),
		keybase1.PGPProtocol(NewPGPHandler(xp, g)),
		keybase1.RevokeProtocol(NewRevokeHandler(xp, g)),
		keybase1.ProveProtocol(NewProveHandler(xp, g)),
		keybase1.SaltpackProtocol(NewSaltpackHandler(xp, g)),
		keybase1.SecretKeysProtocol(NewSecretKeysHandler(xp, g)),
		keybase1.SessionProtocol(NewSessionHandler(xp, g)),
		keybase1.SignupProtocol(NewSignupHandler(xp, g)),
		keybase1.SigsProtocol(NewSigsHandler(xp, g)),
		keybase1.TestProtocol(NewTestHandler(xp, g)),
		keybase1.TrackProtocol(NewTrackHandler(xp, g)),
		keybase1.UpdateProtocol(NewUpdateHandler(xp, g, d.updateChecker)),
		keybase1.UserProtocol(NewUserHandler(xp, g)),
	}
	for _, proto := range protocols {
		if err := srv.Register(proto); err != nil {
			return err
		}
	}
	return nil
}

func (d *Service) Handle(c net.Conn) {
	xp := rpc.NewTransport(c, libkb.NewRPCLogFactory(), libkb.WrapError)

	server := rpc.NewServer(xp, libkb.WrapError)

	cl := make(chan error)
	server.AddCloseListener(cl)
	connID := d.G().NotifyRouter.AddConnection(xp, cl)

	var logReg *logRegister
	if d.isDaemon {
		// Create a new log register object that the Log handler can use to
		// register a logger.  When this function finishes, the logger
		// will be removed.
		logReg = newLogRegister(d.logForwarder, d.G().Log)
		defer logReg.UnregisterLogger()
	}

	if err := d.RegisterProtocols(server, xp, connID, logReg, d.G()); err != nil {
		d.G().Log.Warning("RegisterProtocols error: %s", err)
		return
	}

	if err := server.Run(false /* bg */); err != nil {
		if err != io.EOF {
			d.G().Log.Warning("Run error: %s", err)
		}
	}

	d.G().Log.Debug("Handle() complete for connection %d", connID)
}

func (d *Service) Run() (err error) {

	defer func() {
		if d.startCh != nil {
			close(d.startCh)
		}
		d.G().Log.Debug("From Service.Run(): exit with code %d\n", d.G().ExitCode)
	}()

	d.G().Log.Debug("+ service starting up; forkType=%v", d.ForkType)

	// Sets this global context to "service" mode which will toggle a flag
	// and will also set in motion various go-routine based managers
	d.G().SetService()
	d.G().SetUIRouter(NewUIRouter(d.G()))

	// register the service's logForwarder as the external handler for the log module:
	d.G().Log.SetExternalHandler(d.logForwarder)

	err = d.writeServiceInfo()
	if err != nil {
		return
	}

	if len(d.chdirTo) != 0 {
		etmp := os.Chdir(d.chdirTo)
		if etmp != nil {
			d.G().Log.Warning("Could not change directory to %s: %s", d.chdirTo, etmp)
		} else {
			d.G().Log.Info("Changing runtime dir to %s", d.chdirTo)
		}
	}

	// Explicitly set fork type here based on KEYBASE_LABEL
	if len(d.G().Env.GetLabel()) > 0 {
		d.ForkType = keybase1.ForkType_LAUNCHD
	}

	if err = d.GetExclusiveLock(); err != nil {
		return
	}
	if err = d.OpenSocket(); err != nil {
		return
	}

	var l net.Listener
	if l, err = d.ConfigRPCServer(); err != nil {
		return
	}

	if sources.IsPrerelease {
		updr := engine.NewDefaultUpdater(d.G())
		if updr != nil {
			updateChecker := updater.NewUpdateChecker(updr, d.G().UIRouter, d.G().Log)
			d.updateChecker = &updateChecker
			d.updateChecker.Start()
		}
	}

	d.checkTrackingEveryHour()

	d.G().ExitCode, err = d.ListenLoopWithStopper(l)

	return err
}

func (d *Service) StartLoopbackServer() error {

	var l net.Listener
	var err error

	if err = d.GetExclusiveLock(); err != nil {
		return err
	}

	if l, err = d.G().MakeLoopbackServer(); err != nil {
		return err
	}

	go d.ListenLoop(l)

	return nil
}

func (d *Service) ensureRuntimeDir() (string, error) {
	runtimeDir := d.G().Env.GetRuntimeDir()
	return runtimeDir, os.MkdirAll(runtimeDir, libkb.PermDir)
}

// If the daemon is already running, we need to be able to check what version
// it is, in case the client has been updated.
func (d *Service) writeServiceInfo() error {
	runtimeDir, err := d.ensureRuntimeDir()
	if err != nil {
		return err
	}

	// Write runtime info file
	rtInfo := libkb.KeybaseServiceInfo(d.G())
	return rtInfo.WriteFile(path.Join(runtimeDir, "keybased.info"))
}

func (d *Service) checkTrackingEveryHour() {
	ticker := time.NewTicker(1 * time.Hour)
	go func() {
		for {
			<-ticker.C
			d.G().Log.Debug("Checking tracks on an hour timer.")
			libkb.CheckTracking(d.G())
		}
	}()
}

// ReleaseLock releases the locking pidfile by closing, unlocking and
// deleting it.
func (d *Service) ReleaseLock() error {
	d.G().Log.Debug("Releasing lock file")
	return d.lockPid.Close()
}

// GetExclusiveLockWithoutAutoUnlock grabs the exclusive lock over running
// keybase and continues to hold the lock. The caller is then required to
// manually release this lock via ReleaseLock()
func (d *Service) GetExclusiveLockWithoutAutoUnlock() error {
	if _, err := d.ensureRuntimeDir(); err != nil {
		return err
	}
	if err := d.lockPIDFile(); err != nil {
		return err
	}
	return nil
}

// GetExclusiveLock grabs the exclusive lock over running keybase
// and then installs a shutdown hook to release the lock automatically
// on shutdown.
func (d *Service) GetExclusiveLock() error {
	if err := d.GetExclusiveLockWithoutAutoUnlock(); err != nil {
		return err
	}
	d.G().PushShutdownHook(func() error {
		return d.ReleaseLock()
	})
	return nil
}

func (d *Service) OpenSocket() error {
	sf, err := d.G().Env.GetSocketFile()
	if err != nil {
		return err
	}
	if exists, err := libkb.FileExists(sf); err != nil {
		return err
	} else if exists {
		d.G().Log.Debug("removing stale socket file: %s", sf)
		if err = os.Remove(sf); err != nil {
			d.G().Log.Warning("error removing stale socket file: %s", err)
			return err
		}
	}
	return nil
}

func (d *Service) lockPIDFile() (err error) {
	var fn string
	if fn, err = d.G().Env.GetPidFile(); err != nil {
		return
	}
	d.lockPid = libkb.NewLockPIDFile(fn)
	if err = d.lockPid.Lock(); err != nil {
		return err
	}
	d.G().Log.Debug("Locking pidfile %s\n", fn)
	return nil
}

func (d *Service) ConfigRPCServer() (l net.Listener, err error) {
	if l, err = d.G().BindToSocket(); err != nil {
		return
	}
	if d.startCh != nil {
		close(d.startCh)
		d.startCh = nil
	}
	return
}

func (d *Service) Stop(exitCode keybase1.ExitCode) {
	d.stopCh <- exitCode
}

func (d *Service) ListenLoopWithStopper(l net.Listener) (exitCode keybase1.ExitCode, err error) {
	ch := make(chan error)
	go func() {
		ch <- d.ListenLoop(l)
	}()
	exitCode = <-d.stopCh
	l.Close()
	d.G().Log.Debug("Left listen loop w/ exit code %d\n", exitCode)
	return exitCode, <-ch
}

func (d *Service) ListenLoop(l net.Listener) (err error) {
	d.G().Log.Debug("+ Enter ListenLoop()")
	for {
		var c net.Conn
		if c, err = l.Accept(); err != nil {

			if libkb.IsSocketClosedError(err) {
				err = nil
			}

			d.G().Log.Debug("+ Leaving ListenLoop() w/ error %v", err)
			return
		}
		go d.Handle(c)
	}
}

func (d *Service) ParseArgv(ctx *cli.Context) error {
	d.chdirTo = ctx.String("chdir")
	if ctx.Bool("auto-forked") {
		d.ForkType = keybase1.ForkType_AUTO
	} else if ctx.Bool("watchdog-forked") {
		d.ForkType = keybase1.ForkType_WATCHDOG
	} else if ctx.Bool("launchd-forked") {
		d.ForkType = keybase1.ForkType_LAUNCHD
	}
	return nil
}

func NewCmdService(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name: "service",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "chdir",
				Usage: "Specify where to run as a daemon (via chdir)",
			},
			cli.StringFlag{
				Name:  "label",
				Usage: "Specifying a label can help identify services.",
			},
			cli.BoolFlag{
				Name:  "auto-forked",
				Usage: "Specify if this binary was auto-forked from the client",
			},
			cli.BoolFlag{
				Name:  "watchdog-forked",
				Usage: "Specify if this binary was started by the watchdog",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewService(g, true /* isDaemon */), "service", c)
			cl.SetService()
		},
	}
}

func (d *Service) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:     true,
		KbKeyring:  true,
		GpgKeyring: true,
		API:        true,
		Socket:     true,
	}
}

func GetCommands(cl *libcmdline.CommandLine, g *libkb.GlobalContext) []cli.Command {
	return []cli.Command{
		NewCmdService(cl, g),
	}
}
<commit_msg>commentary<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package service

import (
	"io"
	"net"
	"os"
	"path"
	"time"

	"github.com/keybase/cli"
	"github.com/keybase/client/go/engine"
	"github.com/keybase/client/go/libcmdline"
	"github.com/keybase/client/go/libkb"
	keybase1 "github.com/keybase/client/go/protocol"
	"github.com/keybase/client/go/updater"
	"github.com/keybase/client/go/updater/sources"
	rpc "github.com/keybase/go-framed-msgpack-rpc"
)

type Service struct {
	libkb.Contextified
	isDaemon      bool
	chdirTo       string
	lockPid       *libkb.LockPIDFile
	ForkType      keybase1.ForkType
	startCh       chan struct{}
	stopCh        chan keybase1.ExitCode
	updateChecker *updater.UpdateChecker
	logForwarder  *logFwd
}

func NewService(g *libkb.GlobalContext, isDaemon bool) *Service {
	return &Service{
		Contextified: libkb.NewContextified(g),
		isDaemon:     isDaemon,
		startCh:      make(chan struct{}),
		stopCh:       make(chan keybase1.ExitCode),
		logForwarder: newLogFwd(),
	}
}

func (d *Service) GetStartChannel() <-chan struct{} {
	return d.startCh
}

func (d *Service) RegisterProtocols(srv *rpc.Server, xp rpc.Transporter, connID libkb.ConnectionID, logReg *logRegister, g *libkb.GlobalContext) error {
	protocols := []rpc.Protocol{
		keybase1.AccountProtocol(NewAccountHandler(xp, g)),
		keybase1.BTCProtocol(NewBTCHandler(xp, g)),
		keybase1.ConfigProtocol(NewConfigHandler(xp, g, d)),
		keybase1.CryptoProtocol(NewCryptoHandler(g)),
		keybase1.CtlProtocol(NewCtlHandler(xp, d, g)),
		keybase1.DebuggingProtocol(NewDebuggingHandler(xp)),
		keybase1.DelegateUiCtlProtocol(NewDelegateUICtlHandler(xp, connID, g)),
		keybase1.DeviceProtocol(NewDeviceHandler(xp, g)),
		keybase1.FavoriteProtocol(NewFavoriteHandler(xp, g)),
		keybase1.IdentifyProtocol(NewIdentifyHandler(xp, g)),
		keybase1.KbfsProtocol(NewKBFSHandler(xp, g)),
		keybase1.LogProtocol(NewLogHandler(xp, logReg, g)),
		keybase1.LoginProtocol(NewLoginHandler(xp, g)),
		keybase1.NotifyCtlProtocol(NewNotifyCtlHandler(xp, connID, g)),
		keybase1.PGPProtocol(NewPGPHandler(xp, g)),
		keybase1.RevokeProtocol(NewRevokeHandler(xp, g)),
		keybase1.ProveProtocol(NewProveHandler(xp, g)),
		keybase1.SaltpackProtocol(NewSaltpackHandler(xp, g)),
		keybase1.SecretKeysProtocol(NewSecretKeysHandler(xp, g)),
		keybase1.SessionProtocol(NewSessionHandler(xp, g)),
		keybase1.SignupProtocol(NewSignupHandler(xp, g)),
		keybase1.SigsProtocol(NewSigsHandler(xp, g)),
		keybase1.TestProtocol(NewTestHandler(xp, g)),
		keybase1.TrackProtocol(NewTrackHandler(xp, g)),
		keybase1.UpdateProtocol(NewUpdateHandler(xp, g, d.updateChecker)),
		keybase1.UserProtocol(NewUserHandler(xp, g)),
	}
	for _, proto := range protocols {
		if err := srv.Register(proto); err != nil {
			return err
		}
	}
	return nil
}

func (d *Service) Handle(c net.Conn) {
	xp := rpc.NewTransport(c, libkb.NewRPCLogFactory(), libkb.WrapError)

	server := rpc.NewServer(xp, libkb.WrapError)

	cl := make(chan error)
	server.AddCloseListener(cl)
	connID := d.G().NotifyRouter.AddConnection(xp, cl)

	var logReg *logRegister
	if d.isDaemon {
		// Create a new log register object that the Log handler can use to
		// register a logger.  When this function finishes, the logger
		// will be removed.
		logReg = newLogRegister(d.logForwarder, d.G().Log)
		defer logReg.UnregisterLogger()
	}

	if err := d.RegisterProtocols(server, xp, connID, logReg, d.G()); err != nil {
		d.G().Log.Warning("RegisterProtocols error: %s", err)
		return
	}

	if err := server.Run(false /* bg */); err != nil {
		if err != io.EOF {
			d.G().Log.Warning("Run error: %s", err)
		}
	}

	d.G().Log.Debug("Handle() complete for connection %d", connID)
}

func (d *Service) Run() (err error) {

	defer func() {
		if d.startCh != nil {
			close(d.startCh)
		}
		d.G().Log.Debug("From Service.Run(): exit with code %d\n", d.G().ExitCode)
	}()

	d.G().Log.Debug("+ service starting up; forkType=%v", d.ForkType)

	// Sets this global context to "service" mode which will toggle a flag
	// and will also set in motion various go-routine based managers
	d.G().SetService()
	d.G().SetUIRouter(NewUIRouter(d.G()))

	// register the service's logForwarder as the external handler for the log module:
	d.G().Log.SetExternalHandler(d.logForwarder)

	err = d.writeServiceInfo()
	if err != nil {
		return
	}

	if len(d.chdirTo) != 0 {
		etmp := os.Chdir(d.chdirTo)
		if etmp != nil {
			d.G().Log.Warning("Could not change directory to %s: %s", d.chdirTo, etmp)
		} else {
			d.G().Log.Info("Changing runtime dir to %s", d.chdirTo)
		}
	}

	// Explicitly set fork type here based on KEYBASE_LABEL.
	// This is for OSX-based Launchd implementations, which unfortunately
	// don't obey the same command-line flag conventions as
	// the other platforms.
	if len(d.G().Env.GetLabel()) > 0 {
		d.ForkType = keybase1.ForkType_LAUNCHD
	}

	if err = d.GetExclusiveLock(); err != nil {
		return
	}
	if err = d.OpenSocket(); err != nil {
		return
	}

	var l net.Listener
	if l, err = d.ConfigRPCServer(); err != nil {
		return
	}

	if sources.IsPrerelease {
		updr := engine.NewDefaultUpdater(d.G())
		if updr != nil {
			updateChecker := updater.NewUpdateChecker(updr, d.G().UIRouter, d.G().Log)
			d.updateChecker = &updateChecker
			d.updateChecker.Start()
		}
	}

	d.checkTrackingEveryHour()

	d.G().ExitCode, err = d.ListenLoopWithStopper(l)

	return err
}

func (d *Service) StartLoopbackServer() error {

	var l net.Listener
	var err error

	if err = d.GetExclusiveLock(); err != nil {
		return err
	}

	if l, err = d.G().MakeLoopbackServer(); err != nil {
		return err
	}

	go d.ListenLoop(l)

	return nil
}

func (d *Service) ensureRuntimeDir() (string, error) {
	runtimeDir := d.G().Env.GetRuntimeDir()
	return runtimeDir, os.MkdirAll(runtimeDir, libkb.PermDir)
}

// If the daemon is already running, we need to be able to check what version
// it is, in case the client has been updated.
func (d *Service) writeServiceInfo() error {
	runtimeDir, err := d.ensureRuntimeDir()
	if err != nil {
		return err
	}

	// Write runtime info file
	rtInfo := libkb.KeybaseServiceInfo(d.G())
	return rtInfo.WriteFile(path.Join(runtimeDir, "keybased.info"))
}

func (d *Service) checkTrackingEveryHour() {
	ticker := time.NewTicker(1 * time.Hour)
	go func() {
		for {
			<-ticker.C
			d.G().Log.Debug("Checking tracks on an hour timer.")
			libkb.CheckTracking(d.G())
		}
	}()
}

// ReleaseLock releases the locking pidfile by closing, unlocking and
// deleting it.
func (d *Service) ReleaseLock() error {
	d.G().Log.Debug("Releasing lock file")
	return d.lockPid.Close()
}

// GetExclusiveLockWithoutAutoUnlock grabs the exclusive lock over running
// keybase and continues to hold the lock. The caller is then required to
// manually release this lock via ReleaseLock()
func (d *Service) GetExclusiveLockWithoutAutoUnlock() error {
	if _, err := d.ensureRuntimeDir(); err != nil {
		return err
	}
	if err := d.lockPIDFile(); err != nil {
		return err
	}
	return nil
}

// GetExclusiveLock grabs the exclusive lock over running keybase
// and then installs a shutdown hook to release the lock automatically
// on shutdown.
func (d *Service) GetExclusiveLock() error {
	if err := d.GetExclusiveLockWithoutAutoUnlock(); err != nil {
		return err
	}
	d.G().PushShutdownHook(func() error {
		return d.ReleaseLock()
	})
	return nil
}

func (d *Service) OpenSocket() error {
	sf, err := d.G().Env.GetSocketFile()
	if err != nil {
		return err
	}
	if exists, err := libkb.FileExists(sf); err != nil {
		return err
	} else if exists {
		d.G().Log.Debug("removing stale socket file: %s", sf)
		if err = os.Remove(sf); err != nil {
			d.G().Log.Warning("error removing stale socket file: %s", err)
			return err
		}
	}
	return nil
}

func (d *Service) lockPIDFile() (err error) {
	var fn string
	if fn, err = d.G().Env.GetPidFile(); err != nil {
		return
	}
	d.lockPid = libkb.NewLockPIDFile(fn)
	if err = d.lockPid.Lock(); err != nil {
		return err
	}
	d.G().Log.Debug("Locking pidfile %s\n", fn)
	return nil
}

func (d *Service) ConfigRPCServer() (l net.Listener, err error) {
	if l, err = d.G().BindToSocket(); err != nil {
		return
	}
	if d.startCh != nil {
		close(d.startCh)
		d.startCh = nil
	}
	return
}

func (d *Service) Stop(exitCode keybase1.ExitCode) {
	d.stopCh <- exitCode
}

func (d *Service) ListenLoopWithStopper(l net.Listener) (exitCode keybase1.ExitCode, err error) {
	ch := make(chan error)
	go func() {
		ch <- d.ListenLoop(l)
	}()
	exitCode = <-d.stopCh
	l.Close()
	d.G().Log.Debug("Left listen loop w/ exit code %d\n", exitCode)
	return exitCode, <-ch
}

func (d *Service) ListenLoop(l net.Listener) (err error) {
	d.G().Log.Debug("+ Enter ListenLoop()")
	for {
		var c net.Conn
		if c, err = l.Accept(); err != nil {

			if libkb.IsSocketClosedError(err) {
				err = nil
			}

			d.G().Log.Debug("+ Leaving ListenLoop() w/ error %v", err)
			return
		}
		go d.Handle(c)
	}
}

func (d *Service) ParseArgv(ctx *cli.Context) error {
	d.chdirTo = ctx.String("chdir")
	if ctx.Bool("auto-forked") {
		d.ForkType = keybase1.ForkType_AUTO
	} else if ctx.Bool("watchdog-forked") {
		d.ForkType = keybase1.ForkType_WATCHDOG
	} else if ctx.Bool("launchd-forked") {
		d.ForkType = keybase1.ForkType_LAUNCHD
	}
	return nil
}

func NewCmdService(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
	return cli.Command{
		Name: "service",
		Flags: []cli.Flag{
			cli.StringFlag{
				Name:  "chdir",
				Usage: "Specify where to run as a daemon (via chdir)",
			},
			cli.StringFlag{
				Name:  "label",
				Usage: "Specifying a label can help identify services.",
			},
			cli.BoolFlag{
				Name:  "auto-forked",
				Usage: "Specify if this binary was auto-forked from the client",
			},
			cli.BoolFlag{
				Name:  "watchdog-forked",
				Usage: "Specify if this binary was started by the watchdog",
			},
		},
		Action: func(c *cli.Context) {
			cl.ChooseCommand(NewService(g, true /* isDaemon */), "service", c)
			cl.SetService()
		},
	}
}

func (d *Service) GetUsage() libkb.Usage {
	return libkb.Usage{
		Config:     true,
		KbKeyring:  true,
		GpgKeyring: true,
		API:        true,
		Socket:     true,
	}
}

func GetCommands(cl *libcmdline.CommandLine, g *libkb.GlobalContext) []cli.Command {
	return []cli.Command{
		NewCmdService(cl, g),
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"

	usercorn "github.com/lunixbochs/usercorn/go"
	"github.com/lunixbochs/usercorn/go/debug"
	"github.com/lunixbochs/usercorn/go/models"
)

type strslice []string

func (s *strslice) String() string {
	return fmt.Sprintf("%v", *s)
}

func (s *strslice) Set(value string) error {
	*s = append(*s, value)
	return nil
}

// like go io.Copy(), but returns a channel to notify you upon completion
func copyNotify(dst io.Writer, src io.Reader) chan int {
	ret := make(chan int)
	go func() {
		io.Copy(dst, src)
		ret <- 1
	}()
	return ret
}

func main() {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	fs := flag.NewFlagSet("cli", flag.ExitOnError)
	verbose := fs.Bool("v", false, "verbose output")
	trace := fs.Bool("trace", false, "recommended tracing options: -loop 8 -strace -mtrace2 -etrace -rtrace")
	strace := fs.Bool("strace", false, "trace syscalls")
	mtrace := fs.Bool("mtrace", false, "trace memory access (single)")
	mtrace2 := fs.Bool("mtrace2", false, "trace memory access (batched)")
	etrace := fs.Bool("etrace", false, "trace execution")
	rtrace := fs.Bool("rtrace", false, "trace register modification")
	match := fs.String("match", "", "trace from specific function(s) (func[,func...][+depth]")
	looproll := fs.Int("loop", 0, "collapse loop blocks of this depth")
	prefix := fs.String("prefix", "", "library load prefix")
	base := fs.Uint64("base", 0, "force executable base address")
	ibase := fs.Uint64("ibase", 0, "force interpreter base address")
	demangle := fs.Bool("demangle", false, "demangle symbols using c++filt")
	strsize := fs.Int("strsize", 30, "limited -strace'd strings to length (0 disables)")
	skipinterp := fs.Bool("nointerp", false, "don't load binary's interpreter")
	native := fs.Bool("native", false, "[stub] use native syscall override (only works if host/guest arch/ABI matches)")

	savepre := fs.String("savepre", "", "save state to file and exit before emulation starts")
	savepost := fs.String("savepost", "", "save state to file after emulation ends")

	listen := fs.Int("listen", -1, "listen for debug connection on localhost:<port>")
	connect := fs.Int("connect", -1, "connect to remote usercorn debugger on localhost:<port>")

	var envSet strslice
	var envUnset strslice
	fs.Var(&envSet, "set", "set environment var in the form name=value")
	fs.Var(&envUnset, "unset", "unset environment variable")

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] <exe> [args...]\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Debug Client: %s -connect <port>\n", os.Args[0])
		fs.PrintDefaults()
	}
	fs.Parse(os.Args[1:])

	// connect to debug server (skips rest of usercorn)
	if *connect > 0 {
		addr := net.JoinHostPort("localhost", strconv.Itoa(*connect))
		if err := debug.RunClient(addr); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}

	// make sure we were passed an executable
	args := fs.Args()
	if len(args) < 1 {
		fs.Usage()
		os.Exit(1)
	}

	// build configuration
	absPrefix := ""
	var err error
	if *prefix != "" {
		absPrefix, err = filepath.Abs(*prefix)
		if err != nil {
			panic(err)
		}
	}
	if *looproll == 0 && *trace {
		*looproll = 8
	}
	config := &models.Config{
		Demangle:        *demangle,
		ForceBase:       *base,
		ForceInterpBase: *ibase,
		LoadPrefix:      absPrefix,
		LoopCollapse:    *looproll,
		NativeFallback:  *native,
		SavePost:        *savepost,
		SavePre:         *savepre,
		SkipInterp:      *skipinterp,
		Strsize:         *strsize,
		TraceExec:       *etrace || *trace,
		TraceMem:        *mtrace,
		TraceMemBatch:   *mtrace2 || *trace,
		TraceReg:        *rtrace || *trace,
		TraceSys:        *strace || *trace,
		Verbose:         *verbose,
	}
	if *match != "" {
		split := strings.SplitN(*match, "+", 2)
		if len(split) > 1 {
			if split[1] == "" {
				config.TraceMatchDepth = 999999
			} else {
				config.TraceMatchDepth, _ = strconv.Atoi(split[1])
			}
		}
		config.TraceMatch = strings.Split(split[0], ",")
	}

	// merge environment with flags
	env := os.Environ()
	envSkip := make(map[string]bool)
	for _, v := range envSet {
		if strings.Contains(v, "=") {
			split := strings.SplitN(v, "=", 2)
			envSkip[split[0]] = true
		} else {
			fmt.Fprintf(os.Stderr, "warning: skipping invalid env set %#v\n", v)
		}
	}
	for _, v := range envUnset {
		envSkip[v] = true
	}
	for _, v := range env {
		if strings.Contains(v, "=") {
			split := strings.SplitN(v, "=", 2)
			if _, ok := envSkip[split[0]]; !ok {
				envSet = append(envSet, v)
			}
		}
	}
	env = envSet

	// check permissions
	if stat, err := os.Stat(args[0]); err != nil {
		panic(err)
	} else if stat.Mode().Perm()&1 != 1 {
		fmt.Fprintf(os.Stderr, "%s: permission denied (no execute bit)\n", args[0])
		os.Exit(1)
	}

	// prep usercorn
	corn, err := usercorn.NewUsercorn(args[0], config)
	if err != nil {
		panic(err)
	}

	// start debug server
	if *listen > 0 {
		debugger := debug.NewDebugger(corn)
		addr := net.JoinHostPort("localhost", strconv.Itoa(*listen))
		if err = debugger.Listen(addr); err != nil {
			fmt.Fprintf(os.Stderr, "error listening on port %d: %v\n", *listen, err)
			os.Exit(1)
		}
	}

	// start executable
	err = corn.Run(args, env)
	if err != nil {
		if e, ok := err.(models.ExitStatus); ok {
			os.Exit(int(e))
		} else {
			panic(err)
		}
	}
}
<commit_msg>allow exec permission in any pos for now<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"net"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"strings"

	usercorn "github.com/lunixbochs/usercorn/go"
	"github.com/lunixbochs/usercorn/go/debug"
	"github.com/lunixbochs/usercorn/go/models"
)

type strslice []string

func (s *strslice) String() string {
	return fmt.Sprintf("%v", *s)
}

func (s *strslice) Set(value string) error {
	*s = append(*s, value)
	return nil
}

// like go io.Copy(), but returns a channel to notify you upon completion
func copyNotify(dst io.Writer, src io.Reader) chan int {
	ret := make(chan int)
	go func() {
		io.Copy(dst, src)
		ret <- 1
	}()
	return ret
}

func main() {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	fs := flag.NewFlagSet("cli", flag.ExitOnError)
	verbose := fs.Bool("v", false, "verbose output")
	trace := fs.Bool("trace", false, "recommended tracing options: -loop 8 -strace -mtrace2 -etrace -rtrace")
	strace := fs.Bool("strace", false, "trace syscalls")
	mtrace := fs.Bool("mtrace", false, "trace memory access (single)")
	mtrace2 := fs.Bool("mtrace2", false, "trace memory access (batched)")
	etrace := fs.Bool("etrace", false, "trace execution")
	rtrace := fs.Bool("rtrace", false, "trace register modification")
	match := fs.String("match", "", "trace from specific function(s) (func[,func...][+depth]")
	looproll := fs.Int("loop", 0, "collapse loop blocks of this depth")
	prefix := fs.String("prefix", "", "library load prefix")
	base := fs.Uint64("base", 0, "force executable base address")
	ibase := fs.Uint64("ibase", 0, "force interpreter base address")
	demangle := fs.Bool("demangle", false, "demangle symbols using c++filt")
	strsize := fs.Int("strsize", 30, "limited -strace'd strings to length (0 disables)")
	skipinterp := fs.Bool("nointerp", false, "don't load binary's interpreter")
	native := fs.Bool("native", false, "[stub] use native syscall override (only works if host/guest arch/ABI matches)")

	savepre := fs.String("savepre", "", "save state to file and exit before emulation starts")
	savepost := fs.String("savepost", "", "save state to file after emulation ends")

	listen := fs.Int("listen", -1, "listen for debug connection on localhost:<port>")
	connect := fs.Int("connect", -1, "connect to remote usercorn debugger on localhost:<port>")

	var envSet strslice
	var envUnset strslice
	fs.Var(&envSet, "set", "set environment var in the form name=value")
	fs.Var(&envUnset, "unset", "unset environment variable")

	fs.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [options] <exe> [args...]\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Debug Client: %s -connect <port>\n", os.Args[0])
		fs.PrintDefaults()
	}
	fs.Parse(os.Args[1:])

	// connect to debug server (skips rest of usercorn)
	if *connect > 0 {
		addr := net.JoinHostPort("localhost", strconv.Itoa(*connect))
		if err := debug.RunClient(addr); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}

	// make sure we were passed an executable
	args := fs.Args()
	if len(args) < 1 {
		fs.Usage()
		os.Exit(1)
	}

	// build configuration
	absPrefix := ""
	var err error
	if *prefix != "" {
		absPrefix, err = filepath.Abs(*prefix)
		if err != nil {
			panic(err)
		}
	}
	if *looproll == 0 && *trace {
		*looproll = 8
	}
	config := &models.Config{
		Demangle:        *demangle,
		ForceBase:       *base,
		ForceInterpBase: *ibase,
		LoadPrefix:      absPrefix,
		LoopCollapse:    *looproll,
		NativeFallback:  *native,
		SavePost:        *savepost,
		SavePre:         *savepre,
		SkipInterp:      *skipinterp,
		Strsize:         *strsize,
		TraceExec:       *etrace || *trace,
		TraceMem:        *mtrace,
		TraceMemBatch:   *mtrace2 || *trace,
		TraceReg:        *rtrace || *trace,
		TraceSys:        *strace || *trace,
		Verbose:         *verbose,
	}
	if *match != "" {
		split := strings.SplitN(*match, "+", 2)
		if len(split) > 1 {
			if split[1] == "" {
				config.TraceMatchDepth = 999999
			} else {
				config.TraceMatchDepth, _ = strconv.Atoi(split[1])
			}
		}
		config.TraceMatch = strings.Split(split[0], ",")
	}

	// merge environment with flags
	env := os.Environ()
	envSkip := make(map[string]bool)
	for _, v := range envSet {
		if strings.Contains(v, "=") {
			split := strings.SplitN(v, "=", 2)
			envSkip[split[0]] = true
		} else {
			fmt.Fprintf(os.Stderr, "warning: skipping invalid env set %#v\n", v)
		}
	}
	for _, v := range envUnset {
		envSkip[v] = true
	}
	for _, v := range env {
		if strings.Contains(v, "=") {
			split := strings.SplitN(v, "=", 2)
			if _, ok := envSkip[split[0]]; !ok {
				envSet = append(envSet, v)
			}
		}
	}
	env = envSet

	// check permissions
	if stat, err := os.Stat(args[0]); err != nil {
		panic(err)
	} else if stat.Mode().Perm()&0111 == 0 {
		fmt.Fprintf(os.Stderr, "%s: permission denied (no execute bit)\n", args[0])
		os.Exit(1)
	}

	// prep usercorn
	corn, err := usercorn.NewUsercorn(args[0], config)
	if err != nil {
		panic(err)
	}

	// start debug server
	if *listen > 0 {
		debugger := debug.NewDebugger(corn)
		addr := net.JoinHostPort("localhost", strconv.Itoa(*listen))
		if err = debugger.Listen(addr); err != nil {
			fmt.Fprintf(os.Stderr, "error listening on port %d: %v\n", *listen, err)
			os.Exit(1)
		}
	}

	// start executable
	err = corn.Run(args, env)
	if err != nil {
		if e, ok := err.(models.ExitStatus); ok {
			os.Exit(int(e))
		} else {
			panic(err)
		}
	}
}
<|endoftext|>


<commit_before>package gocloud

import (
	"errors"
	"fmt"
	"github.com/cloudlibz/gocloud/auth"
	"github.com/cloudlibz/gocloud/aws"
	"github.com/cloudlibz/gocloud/google"
)

// Gocloud is a interface which hides the differece between different cloud providers.
type Gocloud interface {
	Createnode(request interface{}) (resp interface{}, err error)
	Startnode(request interface{}) (resp interface{}, err error)
	Stopnode(request interface{}) (resp interface{}, err error)
	Deletenode(request interface{}) (resp interface{}, err error)
	Rebootnode(request interface{}) (resp interface{}, err error)
	Createdisk(request interface{}) (resp interface{}, err error)
	Deletedisk(request interface{}) (resp interface{}, err error)
	Createsnapshot(request interface{}) (resp interface{}, err error)
	Deletesnapshot(request interface{}) (resp interface{}, err error)
	Attachdisk(request interface{}) (resp interface{}, err error)
	Detachdisk(request interface{}) (resp interface{}, err error)
	Creatloadbalancer(request interface{}) (resp interface{}, err error)
	Deleteloadbalancer(request interface{}) (resp interface{}, err error)
	Listloadbalancer(request interface{}) (resp interface{}, err error)
	Attachnodewithloadbalancer(request interface{}) (resp interface{}, err error)
	Detachnodewithloadbalancer(request interface{}) (resp interface{}, err error)
	Createcluster(request interface{}) (resp interface{}, err error)
	Deletecluster(request interface{}) (resp interface{}, err error)
	Createservice(request interface{}) (resp interface{}, err error)
	Runtask(request interface{}) (resp interface{}, err error)
	Deleteservice(request interface{}) (resp interface{}, err error)
	Stoptask(request interface{}) (resp interface{}, err error)
	Starttask(request interface{}) (resp interface{}, err error)
	Listdns(request interface{}) (resp interface{}, err error)
	Createdns(request interface{}) (resp interface{}, err error)
	Deletedns(request interface{}) (resp interface{}, err error)
	ListResourcednsRecordSets(request interface{}) (resp interface{}, err error)
}

const (
	// Amazonprovider reperents Amazon cloud.
	Amazonprovider = "aws"
	// Googleprovider reperents Google cloud.
	Googleprovider = "google"
)

// CloudProvider returns the instance of respective cloud and maps it to Gocloud so that we can call
// the method like Createnode on CloudProvider instance.
// This is a delegation of CloudProvider.
func CloudProvider(provider string) (Gocloud, error) {

	switch provider {
	case Amazonprovider:
		// Calls authentication procedure for AWS
		auth.AWSLoadConfig()
		return new(aws.AWS), nil

	case Googleprovider:
		return new(google.Google), nil

	default:
		return nil, errors.New(fmt.Sprintf("Provider %s not recognized.\n", provider))
	}

}
<commit_msg>openstack as provider added<commit_after>package gocloud

import (
	"errors"
	"fmt"
	"github.com/cloudlibz/gocloud/auth"
	"github.com/cloudlibz/gocloud/aws"
	"github.com/cloudlibz/gocloud/google"
	"github.com/cloudlibz/gocloud/openstack"
)

// Gocloud is a interface which hides the differece between different cloud providers.
type Gocloud interface {
	Createnode(request interface{}) (resp interface{}, err error)
	Startnode(request interface{}) (resp interface{}, err error)
	Stopnode(request interface{}) (resp interface{}, err error)
	Deletenode(request interface{}) (resp interface{}, err error)
	Rebootnode(request interface{}) (resp interface{}, err error)
	Createdisk(request interface{}) (resp interface{}, err error)
	Deletedisk(request interface{}) (resp interface{}, err error)
	Createsnapshot(request interface{}) (resp interface{}, err error)
	Deletesnapshot(request interface{}) (resp interface{}, err error)
	Attachdisk(request interface{}) (resp interface{}, err error)
	Detachdisk(request interface{}) (resp interface{}, err error)
	Creatloadbalancer(request interface{}) (resp interface{}, err error)
	Deleteloadbalancer(request interface{}) (resp interface{}, err error)
	Listloadbalancer(request interface{}) (resp interface{}, err error)
	Attachnodewithloadbalancer(request interface{}) (resp interface{}, err error)
	Detachnodewithloadbalancer(request interface{}) (resp interface{}, err error)
	Createcluster(request interface{}) (resp interface{}, err error)
	Deletecluster(request interface{}) (resp interface{}, err error)
	Createservice(request interface{}) (resp interface{}, err error)
	Runtask(request interface{}) (resp interface{}, err error)
	Deleteservice(request interface{}) (resp interface{}, err error)
	Stoptask(request interface{}) (resp interface{}, err error)
	Starttask(request interface{}) (resp interface{}, err error)
	Listdns(request interface{}) (resp interface{}, err error)
	Createdns(request interface{}) (resp interface{}, err error)
	Deletedns(request interface{}) (resp interface{}, err error)
	ListResourcednsRecordSets(request interface{}) (resp interface{}, err error)
}

const (
	// Amazonprovider reperents Amazon cloud.
	Amazonprovider = "aws"

	// Googleprovider reperents Google cloud.
	Googleprovider = "google"

	// Openstackprovider reperents openstack cloud.
	Openstackprovider = "openstack"

)

// CloudProvider returns the instance of respective cloud and maps it to Gocloud so that we can call
// the method like Createnode on CloudProvider instance.
// This is a delegation of CloudProvider.
func CloudProvider(provider string) (Gocloud, error) {

	switch provider {
	case Amazonprovider:
		// Calls authentication procedure for AWS
		auth.AWSLoadConfig()
		return new(aws.AWS), nil

	case Googleprovider:
		return new(google.Google), nil

	case Openstackprovider:
		return new(openstack.Openstack), nil

	default:
		return nil, errors.New(fmt.Sprintf("Provider %s not recognized.\n", provider))
	}

}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/containers/buildah"
	"github.com/containers/buildah/docker"
	"github.com/containers/buildah/util"
	"github.com/containers/image/v5/manifest"
	is "github.com/containers/image/v5/storage"
	"github.com/containers/image/v5/transports/alltransports"
	"github.com/containers/image/v5/types"
	"github.com/containers/storage"
	v1 "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/sirupsen/logrus"
)

func main() {
	if buildah.InitReexec() {
		return
	}

	expectedManifestType := ""
	expectedConfigType := ""

	storeOptions, _ := storage.DefaultStoreOptions(false, 0)
	debug := flag.Bool("debug", false, "turn on debug logging")
	root := flag.String("root", storeOptions.GraphRoot, "storage root directory")
	runroot := flag.String("runroot", storeOptions.RunRoot, "storage runtime directory")
	driver := flag.String("storage-driver", storeOptions.GraphDriverName, "storage driver")
	opts := flag.String("storage-opts", "", "storage option list (comma separated)")
	policy := flag.String("signature-policy", "", "signature policy file")
	mtype := flag.String("expected-manifest-type", buildah.OCIv1ImageManifest, "expected manifest type")
	showm := flag.Bool("show-manifest", false, "output the manifest JSON")
	rebuildm := flag.Bool("rebuild-manifest", false, "rebuild the manifest JSON")
	showc := flag.Bool("show-config", false, "output the configuration JSON")
	rebuildc := flag.Bool("rebuild-config", false, "rebuild the configuration JSON")
	flag.Parse()
	logrus.SetLevel(logrus.ErrorLevel)
	if debug != nil && *debug {
		logrus.SetLevel(logrus.DebugLevel)
	}
	switch *mtype {
	case buildah.OCIv1ImageManifest:
		expectedManifestType = *mtype
		expectedConfigType = v1.MediaTypeImageConfig
	case buildah.Dockerv2ImageManifest:
		expectedManifestType = *mtype
		expectedConfigType = manifest.DockerV2Schema2ConfigMediaType
	case "*":
		expectedManifestType = ""
		expectedConfigType = ""
	default:
		logrus.Errorf("unknown -expected-manifest-type value, expected either %q or %q or %q",
			buildah.OCIv1ImageManifest, buildah.Dockerv2ImageManifest, "*")
		return
	}
	if root != nil {
		storeOptions.GraphRoot = *root
	}
	if runroot != nil {
		storeOptions.RunRoot = *runroot
	}
	if driver != nil {
		storeOptions.GraphDriverName = *driver
	}
	if opts != nil && *opts != "" {
		storeOptions.GraphDriverOptions = strings.Split(*opts, ",")
	}
	systemContext := &types.SystemContext{
		SignaturePolicyPath: *policy,
	}
	args := flag.Args()
	if len(args) == 0 {
		flag.Usage()
		return
	}
	store, err := storage.GetStore(storeOptions)
	if err != nil {
		logrus.Errorf("error opening storage: %v", err)
		os.Exit(1)
	}
	is.Transport.SetStore(store)

	errors := false
	defer func() {
		store.Shutdown(false) // nolint:errcheck
		if errors {
			os.Exit(1)
		}
	}()
	for _, image := range args {
		var ref types.ImageReference
		oImage := v1.Image{}
		dImage := docker.V2Image{}
		oManifest := v1.Manifest{}
		dManifest := docker.V2S2Manifest{}
		manifestType := ""
		configType := ""

		ref, _, err := util.FindImage(store, "", systemContext, image)
		if err != nil {
			ref2, err2 := alltransports.ParseImageName(image)
			if err2 != nil {
				logrus.Errorf("error parsing reference %q to an image: %v", image, err)
				errors = true
				continue
			}
			ref = ref2
		}

		ctx := context.Background()
		img, err := ref.NewImage(ctx, systemContext)
		if err != nil {
			logrus.Errorf("error opening image %q: %v", image, err)
			errors = true
			continue
		}
		defer img.Close()

		config, err := img.ConfigBlob(ctx)
		if err != nil {
			logrus.Errorf("error reading configuration from %q: %v", image, err)
			errors = true
			continue
		}

		manifest, manifestType, err := img.Manifest(ctx)
		if err != nil {
			logrus.Errorf("error reading manifest from %q: %v", image, err)
			errors = true
			continue
		}

		if expectedManifestType != "" && manifestType != expectedManifestType {
			logrus.Errorf("expected manifest type %q in %q, got %q", expectedManifestType, image, manifestType)
			errors = true
			continue
		}

		switch expectedManifestType {
		case buildah.OCIv1ImageManifest:
			err = json.Unmarshal(manifest, &oManifest)
			if err != nil {
				logrus.Errorf("error parsing manifest from %q: %v", image, err)
				errors = true
				continue
			}
			err = json.Unmarshal(config, &oImage)
			if err != nil {
				logrus.Errorf("error parsing config from %q: %v", image, err)
				errors = true
				continue
			}
			manifestType = v1.MediaTypeImageManifest
			configType = oManifest.Config.MediaType
		case buildah.Dockerv2ImageManifest:
			err = json.Unmarshal(manifest, &dManifest)
			if err != nil {
				logrus.Errorf("error parsing manifest from %q: %v", image, err)
				errors = true
				continue
			}
			err = json.Unmarshal(config, &dImage)
			if err != nil {
				logrus.Errorf("error parsing config from %q: %v", image, err)
				errors = true
				continue
			}
			manifestType = dManifest.MediaType
			configType = dManifest.Config.MediaType
		}

		switch manifestType {
		case buildah.OCIv1ImageManifest:
			if rebuildm != nil && *rebuildm {
				err = json.Unmarshal(manifest, &oManifest)
				if err != nil {
					logrus.Errorf("error parsing manifest from %q: %v", image, err)
					errors = true
					continue
				}
				manifest, err = json.Marshal(oManifest)
				if err != nil {
					logrus.Errorf("error rebuilding manifest from %q: %v", image, err)
					errors = true
					continue
				}
			}
			if rebuildc != nil && *rebuildc {
				err = json.Unmarshal(config, &oImage)
				if err != nil {
					logrus.Errorf("error parsing config from %q: %v", image, err)
					errors = true
					continue
				}
				config, err = json.Marshal(oImage)
				if err != nil {
					logrus.Errorf("error rebuilding config from %q: %v", image, err)
					errors = true
					continue
				}
			}
		case buildah.Dockerv2ImageManifest:
			if rebuildm != nil && *rebuildm {
				err = json.Unmarshal(manifest, &dManifest)
				if err != nil {
					logrus.Errorf("error parsing manifest from %q: %v", image, err)
					errors = true
					continue
				}
				manifest, err = json.Marshal(dManifest)
				if err != nil {
					logrus.Errorf("error rebuilding manifest from %q: %v", image, err)
					errors = true
					continue
				}
			}
			if rebuildc != nil && *rebuildc {
				err = json.Unmarshal(config, &dImage)
				if err != nil {
					logrus.Errorf("error parsing config from %q: %v", image, err)
					errors = true
					continue
				}
				config, err = json.Marshal(dImage)
				if err != nil {
					logrus.Errorf("error rebuilding config from %q: %v", image, err)
					errors = true
					continue
				}
			}
		}
		if expectedConfigType != "" && configType != expectedConfigType {
			logrus.Errorf("expected config type %q in %q, got %q", expectedConfigType, image, configType)
			errors = true
			continue
		}
		if showm != nil && *showm {
			fmt.Println(string(manifest))
		}
		if showc != nil && *showc {
			fmt.Println(string(config))
		}
	}
}
<commit_msg>imgtype: reset storage opts if driver overridden<commit_after>package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"os"
	"strings"

	"github.com/containers/buildah"
	"github.com/containers/buildah/docker"
	"github.com/containers/buildah/util"
	"github.com/containers/image/v5/manifest"
	is "github.com/containers/image/v5/storage"
	"github.com/containers/image/v5/transports/alltransports"
	"github.com/containers/image/v5/types"
	"github.com/containers/storage"
	v1 "github.com/opencontainers/image-spec/specs-go/v1"
	"github.com/sirupsen/logrus"
)

func main() {
	if buildah.InitReexec() {
		return
	}

	expectedManifestType := ""
	expectedConfigType := ""

	storeOptions, _ := storage.DefaultStoreOptions(false, 0)
	debug := flag.Bool("debug", false, "turn on debug logging")
	root := flag.String("root", storeOptions.GraphRoot, "storage root directory")
	runroot := flag.String("runroot", storeOptions.RunRoot, "storage runtime directory")
	driver := flag.String("storage-driver", storeOptions.GraphDriverName, "storage driver")
	opts := flag.String("storage-opts", "", "storage option list (comma separated)")
	policy := flag.String("signature-policy", "", "signature policy file")
	mtype := flag.String("expected-manifest-type", buildah.OCIv1ImageManifest, "expected manifest type")
	showm := flag.Bool("show-manifest", false, "output the manifest JSON")
	rebuildm := flag.Bool("rebuild-manifest", false, "rebuild the manifest JSON")
	showc := flag.Bool("show-config", false, "output the configuration JSON")
	rebuildc := flag.Bool("rebuild-config", false, "rebuild the configuration JSON")
	flag.Parse()
	logrus.SetLevel(logrus.ErrorLevel)
	if debug != nil && *debug {
		logrus.SetLevel(logrus.DebugLevel)
	}
	switch *mtype {
	case buildah.OCIv1ImageManifest:
		expectedManifestType = *mtype
		expectedConfigType = v1.MediaTypeImageConfig
	case buildah.Dockerv2ImageManifest:
		expectedManifestType = *mtype
		expectedConfigType = manifest.DockerV2Schema2ConfigMediaType
	case "*":
		expectedManifestType = ""
		expectedConfigType = ""
	default:
		logrus.Errorf("unknown -expected-manifest-type value, expected either %q or %q or %q",
			buildah.OCIv1ImageManifest, buildah.Dockerv2ImageManifest, "*")
		return
	}
	if root != nil {
		storeOptions.GraphRoot = *root
	}
	if runroot != nil {
		storeOptions.RunRoot = *runroot
	}
	if driver != nil {
		storeOptions.GraphDriverName = *driver
		storeOptions.GraphDriverOptions = nil
	}
	if opts != nil && *opts != "" {
		storeOptions.GraphDriverOptions = strings.Split(*opts, ",")
	}
	systemContext := &types.SystemContext{
		SignaturePolicyPath: *policy,
	}
	args := flag.Args()
	if len(args) == 0 {
		flag.Usage()
		return
	}
	store, err := storage.GetStore(storeOptions)
	if err != nil {
		logrus.Errorf("error opening storage: %v", err)
		os.Exit(1)
	}
	is.Transport.SetStore(store)

	errors := false
	defer func() {
		store.Shutdown(false) // nolint:errcheck
		if errors {
			os.Exit(1)
		}
	}()
	for _, image := range args {
		var ref types.ImageReference
		oImage := v1.Image{}
		dImage := docker.V2Image{}
		oManifest := v1.Manifest{}
		dManifest := docker.V2S2Manifest{}
		manifestType := ""
		configType := ""

		ref, _, err := util.FindImage(store, "", systemContext, image)
		if err != nil {
			ref2, err2 := alltransports.ParseImageName(image)
			if err2 != nil {
				logrus.Errorf("error parsing reference %q to an image: %v", image, err)
				errors = true
				continue
			}
			ref = ref2
		}

		ctx := context.Background()
		img, err := ref.NewImage(ctx, systemContext)
		if err != nil {
			logrus.Errorf("error opening image %q: %v", image, err)
			errors = true
			continue
		}
		defer img.Close()

		config, err := img.ConfigBlob(ctx)
		if err != nil {
			logrus.Errorf("error reading configuration from %q: %v", image, err)
			errors = true
			continue
		}

		manifest, manifestType, err := img.Manifest(ctx)
		if err != nil {
			logrus.Errorf("error reading manifest from %q: %v", image, err)
			errors = true
			continue
		}

		if expectedManifestType != "" && manifestType != expectedManifestType {
			logrus.Errorf("expected manifest type %q in %q, got %q", expectedManifestType, image, manifestType)
			errors = true
			continue
		}

		switch expectedManifestType {
		case buildah.OCIv1ImageManifest:
			err = json.Unmarshal(manifest, &oManifest)
			if err != nil {
				logrus.Errorf("error parsing manifest from %q: %v", image, err)
				errors = true
				continue
			}
			err = json.Unmarshal(config, &oImage)
			if err != nil {
				logrus.Errorf("error parsing config from %q: %v", image, err)
				errors = true
				continue
			}
			manifestType = v1.MediaTypeImageManifest
			configType = oManifest.Config.MediaType
		case buildah.Dockerv2ImageManifest:
			err = json.Unmarshal(manifest, &dManifest)
			if err != nil {
				logrus.Errorf("error parsing manifest from %q: %v", image, err)
				errors = true
				continue
			}
			err = json.Unmarshal(config, &dImage)
			if err != nil {
				logrus.Errorf("error parsing config from %q: %v", image, err)
				errors = true
				continue
			}
			manifestType = dManifest.MediaType
			configType = dManifest.Config.MediaType
		}

		switch manifestType {
		case buildah.OCIv1ImageManifest:
			if rebuildm != nil && *rebuildm {
				err = json.Unmarshal(manifest, &oManifest)
				if err != nil {
					logrus.Errorf("error parsing manifest from %q: %v", image, err)
					errors = true
					continue
				}
				manifest, err = json.Marshal(oManifest)
				if err != nil {
					logrus.Errorf("error rebuilding manifest from %q: %v", image, err)
					errors = true
					continue
				}
			}
			if rebuildc != nil && *rebuildc {
				err = json.Unmarshal(config, &oImage)
				if err != nil {
					logrus.Errorf("error parsing config from %q: %v", image, err)
					errors = true
					continue
				}
				config, err = json.Marshal(oImage)
				if err != nil {
					logrus.Errorf("error rebuilding config from %q: %v", image, err)
					errors = true
					continue
				}
			}
		case buildah.Dockerv2ImageManifest:
			if rebuildm != nil && *rebuildm {
				err = json.Unmarshal(manifest, &dManifest)
				if err != nil {
					logrus.Errorf("error parsing manifest from %q: %v", image, err)
					errors = true
					continue
				}
				manifest, err = json.Marshal(dManifest)
				if err != nil {
					logrus.Errorf("error rebuilding manifest from %q: %v", image, err)
					errors = true
					continue
				}
			}
			if rebuildc != nil && *rebuildc {
				err = json.Unmarshal(config, &dImage)
				if err != nil {
					logrus.Errorf("error parsing config from %q: %v", image, err)
					errors = true
					continue
				}
				config, err = json.Marshal(dImage)
				if err != nil {
					logrus.Errorf("error rebuilding config from %q: %v", image, err)
					errors = true
					continue
				}
			}
		}
		if expectedConfigType != "" && configType != expectedConfigType {
			logrus.Errorf("expected config type %q in %q, got %q", expectedConfigType, image, configType)
			errors = true
			continue
		}
		if showm != nil && *showm {
			fmt.Println(string(manifest))
		}
		if showc != nil && *showc {
			fmt.Println(string(config))
		}
	}
}
<|endoftext|>


<commit_before>package httperror

type HTTPError interface {
	Error() string
	Code() int
}
<commit_msg>New httperror API<commit_after>package httperror

import (
	"errors"
	"fmt"
	"net/http"
)

type HTTPError interface {
	Error() string
	Code() int
}

type Error struct {
	code int
	error
}

var _ HTTPError = Error{}

func (e Error) Code() int {
	return e.code
}
func New(args ...interface{}) error {
	code, err := errorFromMsgAndArgs(args)
	return Error{code, err}
}
func Wrap(err error, code int) *Error {
	if err == nil {
		return nil
	}
	return &Error{code, err}
}

func (e *Error) ServeHTTP(w http.ResponseWriter, _ *http.Request) {
	Serve(w, e)
}

func defaultErr(code int) error {
	if status := http.StatusText(code); status != "" {
		return errors.New(status)
	}
	return fmt.Errorf("HTTP Status %d", code)
}

func errorFromMsgAndArgs(args []interface{}) (code int, err error) {
	code = http.StatusInternalServerError
	if len(args) == 0 || args == nil {
		return code, defaultErr(code)
	}
	switch e := args[0].(type) {
	case HTTPError:
		return e.Code(), e
	case int:
		code = e
		if len(args) == 1 {
			return code, defaultErr(code)
		} else {
			_, err = errorFromMsgAndArgs(args[1:])
			return code, err
		}
	case error:
		return code, e
	case string:
		if len(args) == 1 {
			return code, errors.New(e)
		} else {
			return code, fmt.Errorf(e, args[1:]...)
		}
	default:
		return code, errors.New(fmt.Sprint(e))
	}
}

type Handler interface {
	ServeHTTP(w http.ResponseWriter, r *http.Request) error
}

func StdHandler(h Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		err := h.ServeHTTP(w, r)
		Serve(w, err)
	})
}
func Serve(w http.ResponseWriter, err error) {
	if err == nil {
		return
	}
	if e, isHTTP := err.(HTTPError); isHTTP {
		http.Error(w, e.Error(), e.Code())
	}
	http.Error(w, err.Error(), http.StatusInternalServerError)
}
<|endoftext|>


<commit_before>package logger

type DebugRequest struct {
	Args  []string
	Name  string
	Level uint8
}

type DebugResponse struct{}

type PrintRequest struct {
	Args []string
	Name string
}

type PrintResponse struct{}

type SetDebugLevelRequest struct {
	Name  string
	Level int16
}

type SetDebugLevelResponse struct{}
<commit_msg>Add proto/logger.Watch messages.<commit_after>package logger

type DebugRequest struct {
	Args  []string
	Name  string
	Level uint8
}

type DebugResponse struct{}

type PrintRequest struct {
	Args []string
	Name string
}

type PrintResponse struct{}

type SetDebugLevelRequest struct {
	Name  string
	Level int16
}

type SetDebugLevelResponse struct{}

type WatchRequest struct {
	DebugLevel   int16
	DumpBuffer   bool
	ExcludeRegex string // Empty: nothing excluded. Processed after includes.
	IncludeRegex string // Empty: everything included.
	Name         string
}

type WatchResponse struct {
	Error string
} // Log data are streamed afterwards.
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"testing"

	"github.com/evandroflores/claimr/model"
	"github.com/shomali11/slacker"
	"github.com/stretchr/testify/assert"
)

func TestTryToAddDirect(t *testing.T) {
	// will fail if the message is different
	mockResponse, patchReply := createMockReply(t, "this look like a direct message. Containers are related to a channels")
	patchGetEvent := createMockEvent(t, "team", "DIRECT", "user")

	add(new(slacker.Request), mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
}

func TestTryToAddNoName(t *testing.T) {
	mockResponse, patchReply := createMockReply(t, "can not continue without a container name 🙄")
	patchGetEvent := createMockEvent(t, "team", "channel", "user")
	mockRequest, patchParam := createMockRequest(t, map[string]string{"container-name": ""})

	add(mockRequest, mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
	defer patchParam.Unpatch()
}

func TestTryToAddExistentContainer(t *testing.T) {
	containerName := "my-container-exists"
	teamName := "TestTeam"
	channelName := "TestChannel"
	userName := "user"

	container := model.Container{TeamID: teamName, ChannelID: channelName, Name: containerName}
	err := container.Add()
	defer container.Delete()

	assert.NoError(t, err)

	mockResponse, patchReply := createMockReply(t, "There is a container with the same name on this channel. Try a different one.")
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, map[string]string{"container-name": containerName})

	add(mockRequest, mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
	defer patchParam.Unpatch()
}

func TestAddContainer(t *testing.T) {
	containerName := "my-container-ok"
	teamName := "TestTeam"
	channelName := "TestChannel"
	userName := "user"

	msg := fmt.Sprintf("Container `%s` added to channel <#%s>.", containerName, channelName)
	mockResponse, patchReply := createMockReply(t, msg)
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, map[string]string{"container-name": containerName})

	defer func() {
		container, _ := model.GetContainer(teamName, channelName, containerName)
		container.Delete()
	}()

	add(mockRequest, mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
	defer patchParam.Unpatch()
}
<commit_msg>One more test<commit_after>package cmd

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/bouk/monkey"
	"github.com/evandroflores/claimr/model"
	"github.com/shomali11/slacker"
	"github.com/stretchr/testify/assert"
)

func TestTryToAddDirect(t *testing.T) {
	// will fail if the message is different
	mockResponse, patchReply := createMockReply(t, "this look like a direct message. Containers are related to a channels")
	patchGetEvent := createMockEvent(t, "team", "DIRECT", "user")

	add(new(slacker.Request), mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
}

func TestTryToAddNoName(t *testing.T) {
	mockResponse, patchReply := createMockReply(t, "can not continue without a container name 🙄")
	patchGetEvent := createMockEvent(t, "team", "channel", "user")
	mockRequest, patchParam := createMockRequest(t, map[string]string{"container-name": ""})

	add(mockRequest, mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
	defer patchParam.Unpatch()
}

func TestTryToAddExistentContainer(t *testing.T) {
	containerName := "my-container-exists"
	teamName := "TestTeam"
	channelName := "TestChannel"
	userName := "user"

	container := model.Container{TeamID: teamName, ChannelID: channelName, Name: containerName}
	err := container.Add()
	defer container.Delete()

	assert.NoError(t, err)

	mockResponse, patchReply := createMockReply(t, "There is a container with the same name on this channel. Try a different one.")
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, map[string]string{"container-name": containerName})

	add(mockRequest, mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
	defer patchParam.Unpatch()
}

func TestAddError(t *testing.T) {

	guard := monkey.PatchInstanceMethod(reflect.TypeOf(model.Container{}), "Add",
		func(container model.Container) error {
			return fmt.Errorf("simulated error")
		})
	defer guard.Unpatch()

	containerName := "my-container-ok"
	teamName := "TestTeam"
	channelName := "TestChannel"
	userName := "user"

	mockResponse, patchReply := createMockReply(t, "simulated error")
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, map[string]string{"container-name": containerName})

	add(mockRequest, mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
	defer patchParam.Unpatch()
}

func TestAddContainer(t *testing.T) {
	containerName := "my-container-ok"
	teamName := "TestTeam"
	channelName := "TestChannel"
	userName := "user"

	msg := fmt.Sprintf("Container `%s` added to channel <#%s>.", containerName, channelName)
	mockResponse, patchReply := createMockReply(t, msg)
	patchGetEvent := createMockEvent(t, teamName, channelName, userName)
	mockRequest, patchParam := createMockRequest(t, map[string]string{"container-name": containerName})

	defer func() {
		container, _ := model.GetContainer(teamName, channelName, containerName)
		container.Delete()
	}()

	add(mockRequest, mockResponse)

	defer patchReply.Unpatch()
	defer patchGetEvent.Unpatch()
	defer patchParam.Unpatch()
}
<|endoftext|>