<commit_before>package parser

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

type stateFn func(*lexer) stateFn

const (
	itemVersion  itemType = iota // Version string
	itemOperator                 // <, <=, >, >= =
	itemSet                      // Set seperated by whitespace
	itemRange                    // || ,
	itemAdvanced                 // ~, ^, -, x-ranges
	itemError
	itemEOF // End of input

	versionDEL = '.'
	operatorGT = '>'
	operatorGE = ">="
	operatorLT = '<'
	operatorLE = "<="
	operatorEQ = '='

	operatorTR = '~'
	operatorCR = '^'

	operatorRG = '|'
	operatorST = ' '
	operatorHY = '-'

	eof = -1

	numbers string = "0123456789"
	letters        = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"

	dot        = "."
	hyphen     = "-"
	plus       = "+"
	delimiters = dot + hyphen + plus

	allchars  = alphanum + delimiters
	alphanum  = letters + numbers
	wildcards = "Xx*"
)

type itemType int

type item struct {
	typ itemType
	val string
}

func (i item) String() string {
	switch {
	case i.typ == itemEOF:
		return "EOF"
	case i.typ == itemError:
		return i.val
	}
	return fmt.Sprintf("%v", i.val)
}

type lexer struct {
	name  string    // used only for error reports.
	input string    // the string being scanned.
	start int       // start position of this item.
	pos   int       // current position in the input.
	width int       // width of last rune read from input.
	items chan item // channel of scanned items.
}

func lex(input string) (*lexer, chan item) {
	l := &lexer{
		input: input,
		items: make(chan item),
	}
	go l.run() // Concurrently run state machine.
	return l, l.items
}

func (l *lexer) run() {
	for state := lexMain; state != nil; {
		state = state(l)
	}
	close(l.items) // No more tokens will be delivered.
}

// emit passes an item back to the client.
func (l *lexer) emit(t itemType) {
	l.items <- item{t, l.input[l.start:l.pos]}
	l.start = l.pos
}

// next returns the next rune in the input.
func (l *lexer) next() (rn rune) {
	if l.pos >= len(l.input) {
		l.width = 0
		return eof
	}
	rn, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
	l.pos += l.width
	return rn
}

func (l *lexer) ignore() {
	l.start = l.pos
}

// peek returns but does not consume
// the next rune in the input.
func (l *lexer) peek() rune {
	rn := l.next()
	l.backup()
	return rn
}

func (l *lexer) backup() {
	l.pos -= l.width
}

// accept consumes the next rune
// if it's from the valid set.
func (l *lexer) accept(valid string) bool {
	if strings.IndexRune(valid, l.next()) >= 0 {
		return true
	}
	l.backup()
	return false
}

func (l *lexer) check(valid string) bool {
	if strings.IndexRune(valid, l.peek()) >= 0 {
		return true
	}
	return false
}

// acceptRun consumes a run of runes from the valid set.
func (l *lexer) acceptRun(valid string) {
	for strings.IndexRune(valid, l.next()) >= 0 {
	}
	l.backup()
}

func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	l.items <- item{
		itemError,
		fmt.Sprintf(format, args...),
	}
	return nil
}

func lexMain(l *lexer) stateFn {
	switch r := l.next(); {

	case r == eof || r == '\n':
		l.emit(itemEOF) // Useful to make EOF a token.
		return nil      // Stop the run loop.

	case '0' <= r && r <= '9':
		l.backup()
		return lexVersion

	case r == operatorLT:
		l.backup()
		return lexOperator
	case r == operatorGT:
		l.backup()
		return lexOperator
	case r == operatorEQ:
		l.backup()
		return lexOperator
	case r == operatorTR:
		l.backup()
		return lexAdvancedRange
	case r == operatorCR:
		l.backup()
		return lexAdvancedRange
	case r == operatorRG:
		l.backup()
		return lexRange
	case r == operatorST:
		l.backup()
		return lexSet
	default:
		return l.errorf("invalid character:%v: %q", l.pos, string(r))
	}
}

func lexVersion(l *lexer) stateFn {
	l.acceptRun(numbers)

	if l.accept(dot) {
		if l.accept(numbers) {
			l.acceptRun(numbers)

			if l.accept(dot) {
				if l.accept(numbers) {
					l.acceptRun(numbers)

					if l.accept("+-") {
						l.acceptRun(allchars)
					}
					l.emit(itemVersion)
					return lexMain
				}
			}
		}
	}
	return l.errorf("invalid character:%v: %q", l.pos, string(l.next()))
}

func lexOperator(l *lexer) stateFn {
	l.accept(string(operatorGT) + string(operatorLT))
	l.accept(string(operatorEQ))
	if !l.check(numbers) {
		return l.errorf("invalid character:%v: %q", l.pos, string(l.next()))
	}
	l.emit(itemOperator)
	return lexMain
}

func lexSet(l *lexer) stateFn {
	if l.accept(string(operatorST)) {
		if l.peek() == operatorRG {
			l.ignore()
			return lexRange
		}
		if l.peek() == operatorHY {
			l.ignore()
			return lexAdvancedRange
		}
		l.emit(itemSet)
	}
	return lexMain
}

func lexRange(l *lexer) stateFn {
	l.accept(string(operatorRG))
	if l.accept(string(operatorRG)) {
		l.emit(itemRange)
		if l.peek() == operatorST {
			l.next()
			l.ignore()
		}
		return lexMain
	}
	return l.errorf("invalid character:%v: %q", l.pos, string(l.next()))

}

func lexAdvancedRange(l *lexer) stateFn {
	if l.accept(string(operatorHY)) {
		l.emit(itemAdvanced)
		if l.peek() == operatorST {
			l.next()
			l.ignore()
		}
		return lexMain
	}
	if l.accept(string(operatorCR)) {
		l.emit(itemAdvanced)
		return lexMain
	}
	if l.accept(string(operatorTR)) {
		l.emit(itemAdvanced)
	}
	return lexMain
}

func lexAdvancedVersion(l *lexer) stateFn {

	for i := 0; i <= 2; i++ {
		if !l.accept(wildcards) {
			if !l.accept(numbers) {
				return l.errorf("invalidc character:%v: %q", l.pos, string(l.next()))
			}
			l.acceptRun(numbers)
		}
		if i == 2 {
			if l.accept("+-") {
				l.acceptRun(allchars)
			}

			l.emit(itemAdvanced)
			return lexMain
		}

		if !l.accept(dot) {
			p := l.peek()
			if !(p == operatorST || p == eof) {
				return l.errorf("invalidc character:%v: %q", l.pos, string(l.next()))
			}
			l.emit(itemAdvanced)
			return lexMain
		}
	}
	return nil

}
<commit_msg>Added check for version after range.<commit_after>package parser

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

type stateFn func(*lexer) stateFn

const (
	itemVersion  itemType = iota // Version string
	itemOperator                 // <, <=, >, >= =
	itemSet                      // Set seperated by whitespace
	itemRange                    // || ,
	itemAdvanced                 // ~, ^, -, x-ranges
	itemError
	itemEOF // End of input

	versionDEL = '.'
	operatorGT = '>'
	operatorGE = ">="
	operatorLT = '<'
	operatorLE = "<="
	operatorEQ = '='

	operatorTR = '~'
	operatorCR = '^'

	operatorRG = '|'
	operatorST = ' '
	operatorHY = '-'

	eof = -1

	numbers string = "0123456789"
	letters        = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"

	dot        = "."
	hyphen     = "-"
	plus       = "+"
	delimiters = dot + hyphen + plus

	allchars  = alphanum + delimiters
	alphanum  = letters + numbers
	wildcards = "Xx*"
)

type itemType int

type item struct {
	typ itemType
	val string
}

func (i item) String() string {
	switch {
	case i.typ == itemEOF:
		return "EOF"
	case i.typ == itemError:
		return i.val
	}
	return fmt.Sprintf("%v", i.val)
}

type lexer struct {
	name  string    // used only for error reports.
	input string    // the string being scanned.
	start int       // start position of this item.
	pos   int       // current position in the input.
	width int       // width of last rune read from input.
	items chan item // channel of scanned items.
}

func lex(input string) (*lexer, chan item) {
	l := &lexer{
		input: input,
		items: make(chan item),
	}
	go l.run() // Concurrently run state machine.
	return l, l.items
}

func (l *lexer) run() {
	for state := lexMain; state != nil; {
		state = state(l)
	}
	close(l.items) // No more tokens will be delivered.
}

// emit passes an item back to the client.
func (l *lexer) emit(t itemType) {
	l.items <- item{t, l.input[l.start:l.pos]}
	l.start = l.pos
}

// next returns the next rune in the input.
func (l *lexer) next() (rn rune) {
	if l.pos >= len(l.input) {
		l.width = 0
		return eof
	}
	rn, l.width = utf8.DecodeRuneInString(l.input[l.pos:])
	l.pos += l.width
	return rn
}

func (l *lexer) ignore() {
	l.start = l.pos
}

// peek returns but does not consume
// the next rune in the input.
func (l *lexer) peek() rune {
	rn := l.next()
	l.backup()
	return rn
}

func (l *lexer) backup() {
	l.pos -= l.width
}

// accept consumes the next rune
// if it's from the valid set.
func (l *lexer) accept(valid string) bool {
	if strings.IndexRune(valid, l.next()) >= 0 {
		return true
	}
	l.backup()
	return false
}

func (l *lexer) check(valid string) bool {
	if strings.IndexRune(valid, l.peek()) >= 0 {
		return true
	}
	return false
}

// acceptRun consumes a run of runes from the valid set.
func (l *lexer) acceptRun(valid string) {
	for strings.IndexRune(valid, l.next()) >= 0 {
	}
	l.backup()
}

func (l *lexer) errorf(format string, args ...interface{}) stateFn {
	l.items <- item{
		itemError,
		fmt.Sprintf(format, args...),
	}
	return nil
}

func lexMain(l *lexer) stateFn {
	switch r := l.next(); {

	case r == eof || r == '\n':
		l.emit(itemEOF) // Useful to make EOF a token.
		return nil      // Stop the run loop.

	case '0' <= r && r <= '9':
		l.backup()
		return lexVersion

	case r == operatorLT:
		l.backup()
		return lexOperator
	case r == operatorGT:
		l.backup()
		return lexOperator
	case r == operatorEQ:
		l.backup()
		return lexOperator
	case r == operatorTR:
		l.backup()
		return lexAdvancedRange
	case r == operatorCR:
		l.backup()
		return lexAdvancedRange
	case r == operatorRG:
		l.backup()
		return lexRange
	case r == operatorST:
		l.backup()
		return lexSet
	default:
		return l.errorf("invalid character:%v: %q", l.pos, string(r))
	}
}

func lexVersion(l *lexer) stateFn {
	l.acceptRun(numbers)

	if l.accept(dot) {
		if l.accept(numbers) {
			l.acceptRun(numbers)

			if l.accept(dot) {
				if l.accept(numbers) {
					l.acceptRun(numbers)

					if l.accept("+-") {
						l.acceptRun(allchars)
					}
					l.emit(itemVersion)
					return lexMain
				}
			}
		}
	}
	return l.errorf("invalid character:%v: %q", l.pos, string(l.next()))
}

func lexOperator(l *lexer) stateFn {
	l.accept(string(operatorGT) + string(operatorLT))
	l.accept(string(operatorEQ))
	if !l.check(numbers) {
		return l.errorf("invalid character:%v: %q", l.pos, string(l.next()))
	}
	l.emit(itemOperator)
	return lexMain
}

func lexSet(l *lexer) stateFn {
	if l.accept(string(operatorST)) {
		if l.peek() == operatorRG {
			l.ignore()
			return lexRange
		}
		if l.peek() == operatorHY {
			l.ignore()
			return lexAdvancedRange
		}
		l.emit(itemSet)
	}
	return lexMain
}

func lexRange(l *lexer) stateFn {
	l.accept(string(operatorRG))
	if l.accept(string(operatorRG)) {
		l.emit(itemRange)
		if l.peek() == operatorST {
			l.next()
			l.ignore()
		}
		return lexMain
	}
	return l.errorf("invalid character:%v: %q", l.pos, string(l.next()))

}

func lexAdvancedRange(l *lexer) stateFn {
	if l.accept(string(operatorHY)) {
		l.emit(itemAdvanced)
		if l.peek() == operatorST {
			l.next()
			l.ignore()
		}
		return lexMain
	}
	if l.accept(string(operatorCR) + string(operatorTR)) {
		l.emit(itemAdvanced)

		if !l.check(numbers) {
			return l.errorf("invalid character:%v: %q", l.pos, string(l.next()))
		}
	}

	return lexMain
}

func lexAdvancedVersion(l *lexer) stateFn {

	for i := 0; i <= 2; i++ {
		if !l.accept(wildcards) {
			if !l.accept(numbers) {
				return l.errorf("invalidc character:%v: %q", l.pos, string(l.next()))
			}
			l.acceptRun(numbers)
		}
		if i == 2 {
			if l.accept("+-") {
				l.acceptRun(allchars)
			}

			l.emit(itemAdvanced)
			return lexMain
		}

		if !l.accept(dot) {
			p := l.peek()
			if !(p == operatorST || p == eof) {
				return l.errorf("invalidc character:%v: %q", l.pos, string(l.next()))
			}
			l.emit(itemAdvanced)
			return lexMain
		}
	}
	return nil

}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package git

import (
	"errors"
	"fmt"
	"net/url"
	"path"

	gerritsource "k8s.io/test-infra/prow/gerrit/source"
)

// RemoteResolverFactory knows how to construct remote resolvers for
// authoritative central remotes (to pull from) and publish remotes
// (to push to) for a repository. These resolvers are called at run-time
// to determine remotes for git commands.
type RemoteResolverFactory interface {
	// CentralRemote returns a resolver for a remote server with an
	// authoritative version of the repository. This type of remote
	// is useful for fetching refs and cloning.
	CentralRemote(org, repo string) RemoteResolver
	// PublishRemote returns a resolver for a remote server with a
	// personal fork of the repository. This type of remote is most
	// useful for publishing local changes.
	PublishRemote(org, repo string) RemoteResolver
}

// RemoteResolver knows how to construct a remote URL for git calls
type RemoteResolver func() (string, error)

// LoginGetter fetches a GitHub login on-demand
type LoginGetter func() (login string, err error)

// TokenGetter fetches a GitHub OAuth token on-demand
type TokenGetter func() []byte

type sshRemoteResolverFactory struct {
	host     string
	username LoginGetter
}

// CentralRemote creates a remote resolver that refers to an authoritative remote
// for the repository.
func (f *sshRemoteResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	remote := fmt.Sprintf("git@%s:%s/%s.git", f.host, org, repo)
	return func() (string, error) {
		return remote, nil
	}
}

// PublishRemote creates a remote resolver that refers to a user's remote
// for the repository that can be published to.
func (f *sshRemoteResolverFactory) PublishRemote(_, repo string) RemoteResolver {
	return func() (string, error) {
		org, err := f.username()
		if err != nil {
			return "", err
		}
		return fmt.Sprintf("git@%s:%s/%s.git", f.host, org, repo), nil
	}
}

type httpResolverFactory struct {
	host string
	// Optional, either both or none must be set
	username LoginGetter
	token    TokenGetter
}

// CentralRemote creates a remote resolver that refers to an authoritative remote
// for the repository.
func (f *httpResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	return HttpResolver(func() (*url.URL, error) {
		return &url.URL{Scheme: "https", Host: f.host, Path: fmt.Sprintf("%s/%s", org, repo)}, nil
	}, f.username, f.token)
}

// PublishRemote creates a remote resolver that refers to a user's remote
// for the repository that can be published to.
func (f *httpResolverFactory) PublishRemote(_, repo string) RemoteResolver {
	return HttpResolver(func() (*url.URL, error) {
		if f.username == nil {
			return nil, errors.New("username not configured, no publish repo available")
		}
		o, err := f.username()
		if err != nil {
			return nil, err
		}
		return &url.URL{Scheme: "https", Host: f.host, Path: fmt.Sprintf("%s/%s", o, repo)}, nil
	}, f.username, f.token)
}

// HttpResolver builds http URLs that may optionally contain simple auth credentials, resolved dynamically.
func HttpResolver(remote func() (*url.URL, error), username LoginGetter, token TokenGetter) RemoteResolver {
	return func() (string, error) {
		remote, err := remote()
		if err != nil {
			return "", fmt.Errorf("could not resolve remote: %w", err)
		}

		if username != nil {
			name, err := username()
			if err != nil {
				return "", fmt.Errorf("could not resolve username: %w", err)
			}
			remote.User = url.UserPassword(name, string(token()))
		}

		return remote.String(), nil
	}
}

// pathResolverFactory generates resolvers for local path-based repositories,
// used in local integration testing only
type pathResolverFactory struct {
	baseDir string
}

// CentralRemote creates a remote resolver that refers to an authoritative remote
// for the repository.
func (f *pathResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return path.Join(f.baseDir, org, repo), nil
	}
}

// PublishRemote creates a remote resolver that refers to a user's remote
// for the repository that can be published to.
func (f *pathResolverFactory) PublishRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return path.Join(f.baseDir, org, repo), nil
	}
}

// gerritResolverFactory is meant to be used by Gerrit only. It's so diffrent
// from GitHub that there is no way any of the remotes logic can be shared
// between these two providers. The resulting CentralRemote and PublishRemote
// are both the clone URI.
type gerritResolverFactory struct{}

func (f *gerritResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return gerritsource.CloneURIFromOrgRepo(org, repo), nil
	}
}

func (f *gerritResolverFactory) PublishRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return gerritsource.CloneURIFromOrgRepo(org, repo), nil
	}
}
<commit_msg>fix typo<commit_after>/*
Copyright 2019 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package git

import (
	"errors"
	"fmt"
	"net/url"
	"path"

	gerritsource "k8s.io/test-infra/prow/gerrit/source"
)

// RemoteResolverFactory knows how to construct remote resolvers for
// authoritative central remotes (to pull from) and publish remotes
// (to push to) for a repository. These resolvers are called at run-time
// to determine remotes for git commands.
type RemoteResolverFactory interface {
	// CentralRemote returns a resolver for a remote server with an
	// authoritative version of the repository. This type of remote
	// is useful for fetching refs and cloning.
	CentralRemote(org, repo string) RemoteResolver
	// PublishRemote returns a resolver for a remote server with a
	// personal fork of the repository. This type of remote is most
	// useful for publishing local changes.
	PublishRemote(org, repo string) RemoteResolver
}

// RemoteResolver knows how to construct a remote URL for git calls
type RemoteResolver func() (string, error)

// LoginGetter fetches a GitHub login on-demand
type LoginGetter func() (login string, err error)

// TokenGetter fetches a GitHub OAuth token on-demand
type TokenGetter func() []byte

type sshRemoteResolverFactory struct {
	host     string
	username LoginGetter
}

// CentralRemote creates a remote resolver that refers to an authoritative remote
// for the repository.
func (f *sshRemoteResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	remote := fmt.Sprintf("git@%s:%s/%s.git", f.host, org, repo)
	return func() (string, error) {
		return remote, nil
	}
}

// PublishRemote creates a remote resolver that refers to a user's remote
// for the repository that can be published to.
func (f *sshRemoteResolverFactory) PublishRemote(_, repo string) RemoteResolver {
	return func() (string, error) {
		org, err := f.username()
		if err != nil {
			return "", err
		}
		return fmt.Sprintf("git@%s:%s/%s.git", f.host, org, repo), nil
	}
}

type httpResolverFactory struct {
	host string
	// Optional, either both or none must be set
	username LoginGetter
	token    TokenGetter
}

// CentralRemote creates a remote resolver that refers to an authoritative remote
// for the repository.
func (f *httpResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	return HttpResolver(func() (*url.URL, error) {
		return &url.URL{Scheme: "https", Host: f.host, Path: fmt.Sprintf("%s/%s", org, repo)}, nil
	}, f.username, f.token)
}

// PublishRemote creates a remote resolver that refers to a user's remote
// for the repository that can be published to.
func (f *httpResolverFactory) PublishRemote(_, repo string) RemoteResolver {
	return HttpResolver(func() (*url.URL, error) {
		if f.username == nil {
			return nil, errors.New("username not configured, no publish repo available")
		}
		o, err := f.username()
		if err != nil {
			return nil, err
		}
		return &url.URL{Scheme: "https", Host: f.host, Path: fmt.Sprintf("%s/%s", o, repo)}, nil
	}, f.username, f.token)
}

// HttpResolver builds http URLs that may optionally contain simple auth credentials, resolved dynamically.
func HttpResolver(remote func() (*url.URL, error), username LoginGetter, token TokenGetter) RemoteResolver {
	return func() (string, error) {
		remote, err := remote()
		if err != nil {
			return "", fmt.Errorf("could not resolve remote: %w", err)
		}

		if username != nil {
			name, err := username()
			if err != nil {
				return "", fmt.Errorf("could not resolve username: %w", err)
			}
			remote.User = url.UserPassword(name, string(token()))
		}

		return remote.String(), nil
	}
}

// pathResolverFactory generates resolvers for local path-based repositories,
// used in local integration testing only
type pathResolverFactory struct {
	baseDir string
}

// CentralRemote creates a remote resolver that refers to an authoritative remote
// for the repository.
func (f *pathResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return path.Join(f.baseDir, org, repo), nil
	}
}

// PublishRemote creates a remote resolver that refers to a user's remote
// for the repository that can be published to.
func (f *pathResolverFactory) PublishRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return path.Join(f.baseDir, org, repo), nil
	}
}

// gerritResolverFactory is meant to be used by Gerrit only. It's so different
// from GitHub that there is no way any of the remotes logic can be shared
// between these two providers. The resulting CentralRemote and PublishRemote
// are both the clone URI.
type gerritResolverFactory struct{}

func (f *gerritResolverFactory) CentralRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return gerritsource.CloneURIFromOrgRepo(org, repo), nil
	}
}

func (f *gerritResolverFactory) PublishRemote(org, repo string) RemoteResolver {
	return func() (string, error) {
		return gerritsource.CloneURIFromOrgRepo(org, repo), nil
	}
}
<|endoftext|>


<commit_before>package slave

import (
	"fmt"
	"github.com/KIT-MAMID/mamid/msp"
	"golang.org/x/sys/unix"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

// TODO make all these constants defaults for CLI parameters.
const DataDBDir = "db"

// Create directories managed by ProcessManager
// returns nil if already exists and permissions are suitable
func (p *ProcessManager) CreateManagedDirs() (err error) {

	if err = unix.Access(p.dataDir, unix.W_OK); err != nil {
		return fmt.Errorf("`%s` does not exist or is not writable", p.dataDir)
	}

	if err = unix.Access(p.dataDir, unix.R_OK|unix.W_OK|unix.X_OK); err != nil {
		if err := os.Mkdir(p.dataDir, os.ModeDir|0700); err != nil {
			return err
		}
	}

	return nil

}

// Create root directory for a process in a subdirectory of
// a directory created by CreateManagedDirs()
// returns nil if already exists and permissions are suitable
func (p *ProcessManager) createDirSkeleton(m msp.Mongod) (err error) {

	const skeletonDirPermissions = 0700

	if err = os.MkdirAll(p.processRootDir(m), os.ModeDir|skeletonDirPermissions); err != nil {
		goto wrapError
	}

	if err = os.MkdirAll(p.processDBPathDir(m), os.ModeDir|skeletonDirPermissions); err != nil {
		goto wrapError
	}

	if err = os.MkdirAll(p.processConfDir(m), os.ModeDir|skeletonDirPermissions); err != nil {
		goto wrapError
	}

	return nil

wrapError:
	return fmt.Errorf("could not create directory skeleton for Mongod: %s", err)

}

func (p *ProcessManager) destroyDataDirectory(m msp.Mongod) error {
	return os.RemoveAll(p.processRootDir(m))
}

// Generate list of process root directories in process root directory tree
func (p *ProcessManager) parseProcessDirTree() (replSetNameByPortNumber map[msp.PortNumber]string, err error) {

	entries, err := ioutil.ReadDir(p.dataDir)
	if err != nil {
		return
	}

	replSetNameByPortNumber = make(map[msp.PortNumber]string)
	for _, entry := range entries {
		if entry.IsDir() {
			port, replSet, err := p.parseProcessRootDirentry(entry)
			if err != nil {
				log.Error(err)
			} else {
				replSetNameByPortNumber[port] = replSet
			}
		} else {
			log.Errorf("unexpected directory entry in `%s`: `%s` (not a directory)", entry.Name())
			continue
		}
	}

	return

}

// Root directory of a process
// process data should not be directly stored there
func (p *ProcessManager) processRootDir(m msp.Mongod) string {
	return filepath.Join(p.dataDir, DataDBDir, fmt.Sprintf("%d:%s", m.Port, m.ReplicaSetConfig.ReplicaSetName))
}

// Given a direntry (no prefix!), extract the data encoded in the direntry
func (p *ProcessManager) parseProcessRootDirentry(entry os.FileInfo) (port msp.PortNumber, replSet string, err error) {
	dirname := entry.Name()
	colonLoc := strings.Index(entry.Name(), ":")
	if colonLoc < 0 {
		err = fmt.Errorf("directory with unparsable name `%s` in db dir", entry.Name())
		return
	}
	portStr := dirname[0:colonLoc]
	port64, parseErr := strconv.ParseUint(portStr, 10, 16)
	if parseErr != nil {
		err = fmt.Errorf("could not parse port number `%s`", portStr)
		return
	}
	port = msp.PortNumber(port64)
	replSet = dirname[colonLoc+1:]
	return
}

func (p *ProcessManager) processDBPathDir(m msp.Mongod) string {
	return filepath.Join(p.processRootDir(m), "dbpath")
}

func (p *ProcessManager) processConfDir(m msp.Mongod) string {
	return filepath.Join(p.processRootDir(m), "conf")
}

func (p *ProcessManager) processKeyfilePath(m msp.Mongod) string {
	return filepath.Join(p.processConfDir(m), "keyfile")
}
<commit_msg>FIX: slave/procmgr_fs: create directory for processRoots<commit_after>package slave

import (
	"fmt"
	"github.com/KIT-MAMID/mamid/msp"
	"golang.org/x/sys/unix"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

const skeletonDirPermissions = 0700

// Create directories managed by ProcessManager
// returns nil if already exists and permissions are suitable
func (p *ProcessManager) CreateManagedDirs() (err error) {

	if err = unix.Access(p.dataDir, unix.W_OK); err != nil {
		return fmt.Errorf("`%s` does not exist or is not writable", p.dataDir)
	}

	if err = unix.Access(p.dataDir, unix.R_OK|unix.W_OK|unix.X_OK); err != nil {
		if err := os.Mkdir(p.managedDirMongods(), os.ModeDir|0700); err != nil {
			return err
		}
	}

	return nil

}

// directory for mongod process root dirs
func (p *ProcessManager) managedDirMongods() string {
	return filepath.Join(p.dataDir, "mongods")
}

// Create root directory for a process in a subdirectory of
// a directory created by CreateManagedDirs()
// returns nil if already exists and permissions are suitable
func (p *ProcessManager) createDirSkeleton(m msp.Mongod) (err error) {

	if err = os.MkdirAll(p.processRootDir(m), os.ModeDir|skeletonDirPermissions); err != nil {
		goto wrapError
	}

	if err = os.MkdirAll(p.processDBPathDir(m), os.ModeDir|skeletonDirPermissions); err != nil {
		goto wrapError
	}

	if err = os.MkdirAll(p.processConfDir(m), os.ModeDir|skeletonDirPermissions); err != nil {
		goto wrapError
	}

	return nil

wrapError:
	return fmt.Errorf("could not create directory skeleton for Mongod: %s", err)

}

func (p *ProcessManager) destroyDataDirectory(m msp.Mongod) error {
	return os.RemoveAll(p.processRootDir(m))
}

// Generate list of process root directories in process root directory tree
func (p *ProcessManager) parseProcessDirTree() (replSetNameByPortNumber map[msp.PortNumber]string, err error) {

	entries, err := ioutil.ReadDir(p.managedDirMongods())
	if err != nil {
		return
	}

	replSetNameByPortNumber = make(map[msp.PortNumber]string)
	for _, entry := range entries {
		if entry.IsDir() {
			port, replSet, err := p.parseProcessRootDirentry(entry)
			if err != nil {
				log.Error(err)
			} else {
				replSetNameByPortNumber[port] = replSet
			}
		} else {
			log.Errorf("unexpected directory entry in `%s`: `%s` (not a directory)", entry.Name())
			continue
		}
	}

	return

}

// Root directory of a process
// process data should not be directly stored there
func (p *ProcessManager) processRootDir(m msp.Mongod) string {
	return filepath.Join(p.managedDirMongods(), fmt.Sprintf("%d:%s", m.Port, m.ReplicaSetConfig.ReplicaSetName))
}

// Given a direntry (no prefix!), extract the data encoded in the direntry
func (p *ProcessManager) parseProcessRootDirentry(entry os.FileInfo) (port msp.PortNumber, replSet string, err error) {
	dirname := entry.Name()
	colonLoc := strings.Index(entry.Name(), ":")
	if colonLoc < 0 {
		err = fmt.Errorf("directory with unparsable name `%s` in db dir", entry.Name())
		return
	}
	portStr := dirname[0:colonLoc]
	port64, parseErr := strconv.ParseUint(portStr, 10, 16)
	if parseErr != nil {
		err = fmt.Errorf("could not parse port number `%s`", portStr)
		return
	}
	port = msp.PortNumber(port64)
	replSet = dirname[colonLoc+1:]
	return
}

func (p *ProcessManager) processDBPathDir(m msp.Mongod) string {
	return filepath.Join(p.processRootDir(m), "dbpath")
}

func (p *ProcessManager) processConfDir(m msp.Mongod) string {
	return filepath.Join(p.processRootDir(m), "conf")
}

func (p *ProcessManager) processKeyfilePath(m msp.Mongod) string {
	return filepath.Join(p.processConfDir(m), "keyfile")
}
<|endoftext|>


<commit_before>package session

import (
	"encoding/gob"
	"errors"
	"log"
	"net/url"

	"github.com/insionng/macross"
)

var GlobalSessions *Manager

var defaultOtions = Options{"memory", `{"cookieName":"MacrossSessionId","gcLifetime":3600}`}

//var defaultOtions = Options{"file", `{"cookieName":"MacrossSessionId","gcLifetime":3600,"ProviderConfig":"./data/session"}`}

//var defaultOtions = Options{"redis", `{"cookieName":"MacrossSessionId","gcLifetime":3600,"ProviderConfig":"127.0.0.1:6379"}`}

const (
	CONTEXT_SESSION_KEY = "_SESSION_STORE"
	COOKIE_FLASH_KEY    = "_COOKIE_FLASH"
	CONTEXT_FLASH_KEY   = "_FLASH_VALUE"
	SESSION_FLASH_KEY   = "_SESSION_FLASH"
	SESSION_INPUT_KEY   = "_SESSION_INPUT"
)

type Options struct {
	Provider string
	Config   string
}

func init() {
	gob.Register(url.Values{})
}

// setup 初始化并设置session配置
func setup(op ...Options) error {
	option := defaultOtions
	if len(op) > 0 {
		option = op[0]
	}

	if len(option.Provider) == 0 {
		option.Provider = defaultOtions.Provider
		option.Config = defaultOtions.Config
	}

	log.Println("Macross session config:", option)

	var err error
	GlobalSessions, err = NewManager(option.Provider, option.Config)
	if err != nil {
		return err
	}
	go GlobalSessions.GC()

	return nil
}

// Sessioner Macross session 中间件
func Sessioner(op ...Options) macross.Handler {
	if err := setup(op...); err != nil {
		log.Fatalln("session errors:", err)
	}
	return func(c *macross.Context) error {
		if GlobalSessions == nil {
			return errors.New("session manager not found, use session middleware but not init ?")
		}

		sess, err := GlobalSessions.SessionStart(c)
		if err != nil {
			return err
		}

		c.Set(CONTEXT_FLASH_KEY, Flash{})

		flashVals := url.Values{}

		flashIf := sess.Get(SESSION_FLASH_KEY)
		if flashIf != nil {
			vals, _ := url.QueryUnescape(flashIf.(string))
			flashVals, _ = url.ParseQuery(vals)
			if len(flashVals) > 0 {
				flash := Flash{}
				flash.ErrorMsg = flashVals.Get("error")
				flash.WarningMsg = flashVals.Get("warning")
				flash.InfoMsg = flashVals.Get("info")
				flash.SuccessMsg = flashVals.Get("success")
				// flash先暂存到context里面
				c.Set(CONTEXT_FLASH_KEY, flash)

			}
		}

		f := NewFlash()

		sess.Set(SESSION_FLASH_KEY, f)

		c.Set(CONTEXT_SESSION_KEY, sess)

		defer func() {
			//log.Println("save session", sess)
			sess.Set(SESSION_FLASH_KEY, url.QueryEscape(f.Encode()))
			sess.SessionRelease(c)
		}()

		return c.Next()
	}
}

func GetStore(c *macross.Context) Store {
	store := c.Get(CONTEXT_SESSION_KEY)
	if store != nil {
		return store.(Store)
	}

	return nil
}

func GetFlash(c *macross.Context) *Flash {
	return GetStore(c).Get(SESSION_FLASH_KEY).(*Flash)
}

func FlashValue(c *macross.Context) Flash {
	return c.Get(CONTEXT_FLASH_KEY).(Flash)
}

func SaveInput(c *macross.Context) {
	GetStore(c).Set(SESSION_INPUT_KEY, url.Values(c.FormParams()))
}

func GetInput(c *macross.Context) url.Values {
	input := GetStore(c).Get(SESSION_INPUT_KEY)
	if input != nil {
		return input.(url.Values)
	}

	return url.Values{}
}

func CleanInput(c *macross.Context) {
	GetStore(c).Set(SESSION_INPUT_KEY, url.Values{})
}

func NewFlash() *Flash {
	return &Flash{url.Values{}, "", "", "", ""}
}

type Flash struct {
	url.Values
	ErrorMsg, WarningMsg, InfoMsg, SuccessMsg string
}

func (f *Flash) set(name, msg string) {
	f.Set(name, msg)
}

func (f *Flash) Error(msg string) {
	f.ErrorMsg = msg
	f.set("error", msg)
}

func (f *Flash) Warning(msg string) {
	f.WarningMsg = msg
	f.set("warning", msg)
}

func (f *Flash) Info(msg string) {
	f.InfoMsg = msg
	f.set("info", msg)
}

func (f *Flash) Success(msg string) {
	f.SuccessMsg = msg
	f.set("success", msg)
}
<commit_msg>update<commit_after>package session

import (
	"encoding/gob"
	"errors"
	"log"
	"net/url"

	"github.com/insionng/macross"
)

var GlobalSessions *Manager

var defaultOtions = Options{"memory", `{"cookieName":"MacrossSessionId","gcLifetime":3600}`}

//var defaultOtions = Options{"file", `{"cookieName":"MacrossSessionId","gcLifetime":3600,"ProviderConfig":"./data/session"}`}

//var defaultOtions = Options{"redis", `{"cookieName":"MacrossSessionId","gcLifetime":3600,"ProviderConfig":"127.0.0.1:6379"}`}

const (
	CONTEXT_SESSION_KEY = "_SESSION_STORE"
	COOKIE_FLASH_KEY    = "_COOKIE_FLASH"
	CONTEXT_FLASH_KEY   = "_FLASH_VALUE"
	SESSION_FLASH_KEY   = "_SESSION_FLASH"
	SESSION_INPUT_KEY   = "_SESSION_INPUT"
)

type Options struct {
	Provider string
	Config   string
}

func init() {
	gob.Register(url.Values{})
}

// setup 初始化并设置session配置
func setup(op ...Options) error {
	option := defaultOtions
	if len(op) > 0 {
		option = op[0]
	}

	if len(option.Provider) == 0 {
		option.Provider = defaultOtions.Provider
		option.Config = defaultOtions.Config
	}

	log.Println("Macross session config:", option)

	var err error
	GlobalSessions, err = NewManager(option.Provider, option.Config)
	if err != nil {
		return err
	}
	go GlobalSessions.GC()

	return nil
}

// Sessioner Macross session 中间件
func Sessioner(op ...Options) macross.Handler {
	if GlobalSessions == nil {
		if err := setup(op...); err != nil {
			log.Fatalln("session errors:", err)
		}
	}
	return func(c *macross.Context) error {
		if GlobalSessions == nil {
			return errors.New("session manager not found, use session middleware but not init ?")
		}

		sess, err := GlobalSessions.SessionStart(c)
		if err != nil {
			return err
		}

		c.Set(CONTEXT_FLASH_KEY, Flash{})

		flashVals := url.Values{}

		flashIf := sess.Get(SESSION_FLASH_KEY)
		if flashIf != nil {
			vals, _ := url.QueryUnescape(flashIf.(string))
			flashVals, _ = url.ParseQuery(vals)
			if len(flashVals) > 0 {
				flash := Flash{}
				flash.ErrorMsg = flashVals.Get("error")
				flash.WarningMsg = flashVals.Get("warning")
				flash.InfoMsg = flashVals.Get("info")
				flash.SuccessMsg = flashVals.Get("success")
				// flash先暂存到context里面
				c.Set(CONTEXT_FLASH_KEY, flash)

			}
		}

		f := NewFlash()

		sess.Set(SESSION_FLASH_KEY, f)

		c.Set(CONTEXT_SESSION_KEY, sess)

		defer func() {
			//log.Println("save session", sess)
			sess.Set(SESSION_FLASH_KEY, url.QueryEscape(f.Encode()))
			sess.SessionRelease(c)
		}()

		return c.Next()
	}
}

func GetStore(c *macross.Context) Store {
	store := c.Get(CONTEXT_SESSION_KEY)
	if store != nil {
		return store.(Store)
	}

	return nil
}

func GetFlash(c *macross.Context) *Flash {
	return GetStore(c).Get(SESSION_FLASH_KEY).(*Flash)
}

func FlashValue(c *macross.Context) Flash {
	return c.Get(CONTEXT_FLASH_KEY).(Flash)
}

func SaveInput(c *macross.Context) {
	GetStore(c).Set(SESSION_INPUT_KEY, url.Values(c.FormParams()))
}

func GetInput(c *macross.Context) url.Values {
	input := GetStore(c).Get(SESSION_INPUT_KEY)
	if input != nil {
		return input.(url.Values)
	}

	return url.Values{}
}

func CleanInput(c *macross.Context) {
	GetStore(c).Set(SESSION_INPUT_KEY, url.Values{})
}

func NewFlash() *Flash {
	return &Flash{url.Values{}, "", "", "", ""}
}

type Flash struct {
	url.Values
	ErrorMsg, WarningMsg, InfoMsg, SuccessMsg string
}

func (f *Flash) set(name, msg string) {
	f.Set(name, msg)
}

func (f *Flash) Error(msg string) {
	f.ErrorMsg = msg
	f.set("error", msg)
}

func (f *Flash) Warning(msg string) {
	f.WarningMsg = msg
	f.set("warning", msg)
}

func (f *Flash) Info(msg string) {
	f.InfoMsg = msg
	f.set("info", msg)
}

func (f *Flash) Success(msg string) {
	f.SuccessMsg = msg
	f.set("success", msg)
}
<|endoftext|>


<commit_before>// Package render is a middleware for Martini that provides easy JSON serialization and HTML template rendering.
//
//  package main
//
//  import (
//    "github.com/codegangsta/martini"
//    "github.com/codegangsta/martini-contrib/render"
//  )
//
//  func main() {
//    m := martini.Classic()
//    m.Use(render.Renderer()) // reads "templates" directory by default
//
//    m.Get("/html", func(r render.Render) {
//      r.HTML(200, "mytemplate", nil)
//    })
//
//    m.Get("/json", func(r render.Render) {
//      r.JSON(200, "hello world")
//    })
//
//    m.Run()
//  }
package render

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/codegangsta/martini"
	"html/template"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
)

const (
	ContentType   = "Content-Type"
	ContentLength = "Content-Length"
	ContentJSON   = "application/json"
	ContentHTML   = "text/html"
)

// Included helper functions for use when rendering html
var helperFuncs = template.FuncMap{
	"yield": func() (string, error) {
		return "", fmt.Errorf("yield called with no layout defined")
	},
}

// Render is a service that can be injected into a Martini handler. Render provides functions for easily writing JSON and
// HTML templates out to a http Response.
type Render interface {
	// JSON writes the given status and JSON serialized version of the given value to the http.ResponseWriter.
	JSON(status int, v interface{})
	// HTML renders a html template specified by the name and writes the result and given status to the http.ResponseWriter.
	HTML(status int, name string, v interface{})
	// Error is a convenience function that writes an http status to the http.ResponseWriter.
	Error(status int)
}

// Options is a struct for specifying configuration options for the render.Renderer middleware
type Options struct {
	// Directory to load templates. Default is "templates"
	Directory string
	// Layout template name. Will not render a layout if "". Defaults to "".
	Layout string
	// Extensions to parse template files from. Defaults to [".tmpl"]
	Extensions []string
	// Funcs is a slice of FuncMaps to apply to the template upon compilation. This is useful for helper functions. Defaults to [].
	Funcs []template.FuncMap
}

// Renderer is a Middleware that maps a render.Render service into the Martini handler chain. An single variadic render.Options
// struct can be optionally provided to configure HTML rendering. The default directory for templates is "templates" and the default
// file extension is ".tmpl".
//
// If MARTINI_ENV is set to "" or "development" then templates will be recompiled on every request. For more performance, set the
// MARTINI_ENV environment variable to "production"
func Renderer(options ...Options) martini.Handler {
	opt := prepareOptions(options)
	t := compile(opt)
	return func(res http.ResponseWriter, c martini.Context) {
		// recompile for easy development
		if martini.Env == martini.Dev {
			t = compile(opt)
		}
		tc, _ := t.Clone()
		c.MapTo(&renderer{res, tc, opt}, (*Render)(nil))
	}
}

func prepareOptions(options []Options) Options {
	var opt Options
	if len(options) > 0 {
		opt = options[0]
	}

	// Defaults
	if len(opt.Directory) == 0 {
		opt.Directory = "templates"
	}
	if len(opt.Extensions) == 0 {
		opt.Extensions = []string{".tmpl"}
	}

	return opt
}

func compile(options Options) *template.Template {
	dir := options.Directory
	t := template.New(dir)
	// parse an initial template in case we don't have any
	template.Must(t.Parse("Martini"))

	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		r, err := filepath.Rel(dir, path)
		if err != nil {
			return err
		}

		ext := filepath.Ext(r)
		for _, extension := range options.Extensions {
			if ext == extension {

				buf, err := ioutil.ReadFile(path)
				if err != nil {
					panic(err)
				}

				name := (r[0 : len(r)-len(ext)])
				tmpl := t.New(filepath.ToSlash(name))

				// add our funcmaps
				for _, funcs := range options.Funcs {
					tmpl.Funcs(funcs)
				}

				// Bomb out if parse fails. We don't want any silent server starts.
				template.Must(tmpl.Funcs(helperFuncs).Parse(string(buf)))
				break
			}
		}

		return nil
	})

	return t
}

type renderer struct {
	http.ResponseWriter
	t   *template.Template
	opt Options
}

func (r *renderer) JSON(status int, v interface{}) {
	result, err := json.Marshal(v)
	if err != nil {
		http.Error(r, err.Error(), 500)
		return
	}

	// json rendered fine, write out the result
	r.Header().Set(ContentType, ContentJSON)
	r.WriteHeader(status)
	r.Write(result)
}

func (r *renderer) HTML(status int, name string, binding interface{}) {
	// assign a layout if there is one
	if len(r.opt.Layout) > 0 {
		r.addYield(name, binding)
		name = r.opt.Layout
	}

	out, err := r.execute(name, binding)
	if err != nil {
		http.Error(r, err.Error(), http.StatusInternalServerError)
	}

	// template rendered fine, write out the result
	r.Header().Set(ContentType, ContentHTML)
	r.Header().Set(ContentLength, strconv.Itoa(out.Len()))
	r.WriteHeader(status)
	io.Copy(r, out)
}

// Error writes the given HTTP status to the current ResponseWriter
func (r *renderer) Error(status int) {
	r.WriteHeader(status)
}

func (r *renderer) execute(name string, binding interface{}) (*bytes.Buffer, error) {
	buf := new(bytes.Buffer)
	return buf, r.t.ExecuteTemplate(buf, name, binding)
}

func (r *renderer) addYield(name string, binding interface{}) {
	funcs := template.FuncMap{
		"yield": func() (template.HTML, error) {
			buf, err := r.execute(name, binding)
			// return safe html here since we are rendering our own template
			return template.HTML(buf.String()), err
		},
	}
	r.t.Funcs(funcs)
}
<commit_msg>-n [Migrated] Added option for left & right delimiters<commit_after>// Package render is a middleware for Martini that provides easy JSON serialization and HTML template rendering.
//
//  package main
//
//  import (
//    "github.com/codegangsta/martini"
//    "github.com/codegangsta/martini-contrib/render"
//  )
//
//  func main() {
//    m := martini.Classic()
//    m.Use(render.Renderer()) // reads "templates" directory by default
//
//    m.Get("/html", func(r render.Render) {
//      r.HTML(200, "mytemplate", nil)
//    })
//
//    m.Get("/json", func(r render.Render) {
//      r.JSON(200, "hello world")
//    })
//
//    m.Run()
//  }
package render

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/codegangsta/martini"
	"html/template"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
)

const (
	ContentType   = "Content-Type"
	ContentLength = "Content-Length"
	ContentJSON   = "application/json"
	ContentHTML   = "text/html"
)

// Included helper functions for use when rendering html
var helperFuncs = template.FuncMap{
	"yield": func() (string, error) {
		return "", fmt.Errorf("yield called with no layout defined")
	},
}

// Render is a service that can be injected into a Martini handler. Render provides functions for easily writing JSON and
// HTML templates out to a http Response.
type Render interface {
	// JSON writes the given status and JSON serialized version of the given value to the http.ResponseWriter.
	JSON(status int, v interface{})
	// HTML renders a html template specified by the name and writes the result and given status to the http.ResponseWriter.
	HTML(status int, name string, v interface{})
	// Error is a convenience function that writes an http status to the http.ResponseWriter.
	Error(status int)
}

// Options is a struct for specifying configuration options for the render.Renderer middleware
type Options struct {
	// Directory to load templates. Default is "templates"
	Directory string
	// Layout template name. Will not render a layout if "". Defaults to "".
	Layout string
	// Extensions to parse template files from. Defaults to [".tmpl"]
	Extensions []string
	// Funcs is a slice of FuncMaps to apply to the template upon compilation. This is useful for helper functions. Defaults to [].
	Funcs []template.FuncMap
	// Left delimiter, defaults to {{
	DelimLeft string
	// Right delimiter, defaults to {{
	DelimRight string
}

// Renderer is a Middleware that maps a render.Render service into the Martini handler chain. An single variadic render.Options
// struct can be optionally provided to configure HTML rendering. The default directory for templates is "templates" and the default
// file extension is ".tmpl".
//
// If MARTINI_ENV is set to "" or "development" then templates will be recompiled on every request. For more performance, set the
// MARTINI_ENV environment variable to "production"
func Renderer(options ...Options) martini.Handler {
	opt := prepareOptions(options)
	t := compile(opt)
	return func(res http.ResponseWriter, c martini.Context) {
		// recompile for easy development
		if martini.Env == martini.Dev {
			t = compile(opt)
		}
		tc, _ := t.Clone()
		c.MapTo(&renderer{res, tc, opt}, (*Render)(nil))
	}
}

func prepareOptions(options []Options) Options {
	var opt Options
	if len(options) > 0 {
		opt = options[0]
	}

	// Defaults
	if len(opt.Directory) == 0 {
		opt.Directory = "templates"
	}
	if len(opt.Extensions) == 0 {
		opt.Extensions = []string{".tmpl"}
	}

	return opt
}

func compile(options Options) *template.Template {
	dir := options.Directory
	t := template.New(dir)
	t.Delims(options.DelimLeft, options.DelimRight)
	// parse an initial template in case we don't have any
	template.Must(t.Parse("Martini"))

	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		r, err := filepath.Rel(dir, path)
		if err != nil {
			return err
		}

		ext := filepath.Ext(r)
		for _, extension := range options.Extensions {
			if ext == extension {

				buf, err := ioutil.ReadFile(path)
				if err != nil {
					panic(err)
				}

				name := (r[0 : len(r)-len(ext)])
				tmpl := t.New(filepath.ToSlash(name))

				// add our funcmaps
				for _, funcs := range options.Funcs {
					tmpl.Funcs(funcs)
				}

				// Bomb out if parse fails. We don't want any silent server starts.
				template.Must(tmpl.Funcs(helperFuncs).Parse(string(buf)))
				break
			}
		}

		return nil
	})

	return t
}

type renderer struct {
	http.ResponseWriter
	t   *template.Template
	opt Options
}

func (r *renderer) JSON(status int, v interface{}) {
	result, err := json.Marshal(v)
	if err != nil {
		http.Error(r, err.Error(), 500)
		return
	}

	// json rendered fine, write out the result
	r.Header().Set(ContentType, ContentJSON)
	r.WriteHeader(status)
	r.Write(result)
}

func (r *renderer) HTML(status int, name string, binding interface{}) {
	// assign a layout if there is one
	if len(r.opt.Layout) > 0 {
		r.addYield(name, binding)
		name = r.opt.Layout
	}

	out, err := r.execute(name, binding)
	if err != nil {
		http.Error(r, err.Error(), http.StatusInternalServerError)
	}

	// template rendered fine, write out the result
	r.Header().Set(ContentType, ContentHTML)
	r.Header().Set(ContentLength, strconv.Itoa(out.Len()))
	r.WriteHeader(status)
	io.Copy(r, out)
}

// Error writes the given HTTP status to the current ResponseWriter
func (r *renderer) Error(status int) {
	r.WriteHeader(status)
}

func (r *renderer) execute(name string, binding interface{}) (*bytes.Buffer, error) {
	buf := new(bytes.Buffer)
	return buf, r.t.ExecuteTemplate(buf, name, binding)
}

func (r *renderer) addYield(name string, binding interface{}) {
	funcs := template.FuncMap{
		"yield": func() (template.HTML, error) {
			buf, err := r.execute(name, binding)
			// return safe html here since we are rendering our own template
			return template.HTML(buf.String()), err
		},
	}
	r.t.Funcs(funcs)
}
<|endoftext|>


<commit_before>package sim

import (
	"fmt"
	"math/rand"

	"github.com/Queens-Hacks/Propagate/sandbox"
)

type TileType int

const (
	DirtTile TileType = iota
	AirTile
	PlantTile
)

type growthRoot struct {
	SpeciesId string
	Loc       Location
	Plant     *Plant
	node      *sandbox.Node
	cache     *sandbox.NewState
}

type Location struct {
	X int `json:"x"`
	Y int `json:"y"`
}

func (l Location) str() string {
	return fmt.Sprintf("%v", l)
}

type superPlusGoodTileStuff struct {
	SpeciesId string   `json:"plantId"`
	Parent    Location `json:"parent"`
	IsRoot    bool     `json:"isRoot"`
	Plant     *Plant
}

type Tile struct {
	Type  TileType                `json:"tileType"`
	Extra *superPlusGoodTileStuff `json:"plant"`
}

type Plant struct {
	Energy      int
	Age         int
	Luck        int
	SpeciesId   string
	tiles       map[string]Location
	terminal    bool
	markedTiles map[Location]Location
	roots       map[*growthRoot]struct{}
}

type Species struct {
	Color  int    `json:"color"`
	Source string `json:"source"`
	Author string `json:"author"`
	refCnt int
}

type gameState struct {
	World    [][]*Tile           `json:"world"`
	Species  map[string]*Species `json:"plants"`
	plants   []*Plant
	roots    map[*growthRoot]struct{}
	maxPlant int
}

type tileDiff struct {
	Loc  Location `json:"loc"`
	Tile Tile     `json:"tile"`
}

type spore struct {
	Location  Location `json:"location"`
	SpeciesId string   `json:"plantId"`
}

func (s *State) AddSpore(loc Location, plantId string) *spore {
	// TODO add in bounds checks
	s.plantAddRef(plantId)
	s.diff.Spores = append(s.diff.Spores, spore{loc, plantId})
	return &s.diff.Spores[len(s.diff.Spores)-1]
}

func (s *State) UpdateSpore(p *spore) bool {
	dx := rand.Intn(3) - 1
	dy := rand.Intn(2)
	p.Location.X += dx
	p.Location.Y += dy
	p.Location.X = (p.Location.X + s.Width()) % s.Width()

	s.Clamp(&p.Location)
	t := s.GetTile(p.Location)
	if t.Type == DirtTile {
		p.Location.Y--
		t = s.GetTile(p.Location)
		// dont plant if not on air tile
		if t.Type != AirTile {
			return true
		}

		plant := s.AddPlant(p.SpeciesId)
		s.AddGrowth(p.Location, plant, "")
		return true
	}
	return false
}

func (s *State) LandSpore(p *spore) {
	// find the spawn the spore
	for y := s.Height() - 1; y > 0; y-- {
		t := s.GetTile(Location{p.Location.X, y})
		if t.Type == AirTile {
			plant := s.AddPlant(p.SpeciesId)
			s.AddGrowth(p.Location, plant, "")
			break
		}
	}

	// remove the spore
	var i int
	for p := range s.diff.Spores {
		i = p
	}
	s.diff.Spores = append(s.diff.Spores[:i], s.diff.Spores[i+1:]...)
}

type diff struct {
	TileDiffs     []tileDiff          `json:"tileDiff"`
	NewPlants     map[string]*Species `json:"newPlants"`
	RemovedPlants []string            `json:"removedPlants"`
	Spores        []spore             `json:"spores"`
}

func (d *diff) isEmpty() bool {
	return len(d.TileDiffs) == 0 && len(d.NewPlants) == 0 && len(d.RemovedPlants) == 0 && len(d.Spores) == 0
}

type State struct {
	state gameState
	diff  diff
}

// Records a reference to a plant, causing the plant to be kept in the structure
func (s *State) plantAddRef(plantId string) {
	species, _ := s.GetSpecies(plantId)
	species.refCnt++
}

// Records a reference to a plant, causing the plant to be removed from the structure
func (s *State) plantRelease(plantId string) {
	plant, _ := s.GetSpecies(plantId)
	plant.refCnt--

	// If the reference count has reached zero, remove the plant from the thing
	if plant.refCnt <= 0 {
		s.diff.RemovedPlants = append(s.diff.RemovedPlants, plantId)
		delete(s.state.Species, plantId)
	}
}

func (s *State) Width() int {
	return len(s.state.World[0])
}

func (s *State) Height() int {
	return len(s.state.World)
}

func (s *State) GetSpecies(plantId string) (*Species, bool) {
	species, ok := s.state.Species[plantId]
	return species, ok
}

// Adds a species to the stateAndDiff, and returns the string key for the plant
// This plant is created with a refCnt of zero
// , but will not be dropped until
// its reference count hits zero again.
func (s *State) AddSpecies(color int, source string, author string) string {
	p := Species{color, source, author, 0}
	s.state.maxPlant += 1
	key := fmt.Sprintf("%d", s.state.maxPlant)
	s.diff.NewPlants[key] = &p
	s.state.Species[key] = &p
	return key
}

func (s *State) GetTile(loc Location) *Tile {
	return s.state.World[loc.Y][loc.X]
}

// Set the tile at a location to a new tile
func (s *State) SetTile(loc Location, new Tile) {
	// XXX FIXME - this is a hack because we get index errors so often here...
	s.Clamp(&loc)

	// Manage the addref and releases
	old := s.GetTile(loc)
	if old.Extra != nil {
		delete(old.Extra.Plant.tiles, loc.str())
	}
	if new.Extra != nil {
		new.Extra.Plant.tiles[loc.str()] = loc
	}

	// Actually update the tile and record the tilediffs
	*old = new
	s.diff.TileDiffs = append(s.diff.TileDiffs, tileDiff{loc, new})
}

func (s *State) ClearPlants() {
	for _, p := range s.state.plants {
		for r := range p.roots {
			s.HaltGrowth(r)
		}
		for _, t := range p.tiles {
			s.SetTile(t, Tile{AirTile, nil})
		}
	}

	s.state.plants = []*Plant{}
}

func (s *State) AddPlant(speciesId string) *Plant {
	s.plantAddRef(speciesId)
	plant := &Plant{100, 0, rand.Intn(6) + 1, speciesId, map[string]Location{}, false, nil, map[*growthRoot]struct{}{}}
	s.state.plants = append(s.state.plants, plant)
	return plant
}

func (s *State) AddGrowth(loc Location, plant *Plant, meta string) *growthRoot {
	if plant == nil {
		panic("crap")
	}
	species, _ := s.GetSpecies(plant.SpeciesId)

	// Create the sandbox node for the plant object
	node := sandbox.AddNode(species.Source, meta)

	// Create the root node for the object, and append it to the roots list
	root := growthRoot{plant.SpeciesId, loc, plant, node, nil}
	s.state.roots[&root] = struct{}{}
	plant.roots[&root] = struct{}{}

	isUnderground := false
	if s.GetTile(loc).Type == DirtTile {
		isUnderground = true
	}

	// Set the tile at the base of the plant to a plant tile
	s.SetTile(loc, Tile{PlantTile, &superPlusGoodTileStuff{plant.SpeciesId, loc, isUnderground, plant}})

	// Return a reference to the root node we previously appended
	return &root
}

func (s *State) lowerToDirt(loc *Location) {
	var base int
	for y := 0; y < s.Height(); y++ {
		t := s.GetTile(Location{loc.X, y})
		if t.Type == DirtTile {
			base = y - 1
			break
		}
	}
	loc.Y = base
}

func (s *State) HaltGrowth(gr *growthRoot) {
	gr.node.Halt()
	delete(s.state.roots, gr)
}
<commit_msg>readme<commit_after>package sim

import (
	"fmt"
	"math/rand"

	"github.com/Queens-Hacks/Propagate/sandbox"
)

type TileType int

const (
	DirtTile TileType = iota
	AirTile
	PlantTile
)

type growthRoot struct {
	SpeciesId string
	Loc       Location
	Plant     *Plant
	node      *sandbox.Node
	cache     *sandbox.NewState
}

type Location struct {
	X int `json:"x"`
	Y int `json:"y"`
}

func (l Location) str() string {
	return fmt.Sprintf("%v", l)
}

type extraTileInfo struct {
	SpeciesId string   `json:"plantId"`
	Parent    Location `json:"parent"`
	IsRoot    bool     `json:"isRoot"`
	Plant     *Plant
}

type Tile struct {
	Type  TileType       `json:"tileType"`
	Extra *extraTileInfo `json:"plant"`
}

type Plant struct {
	Energy      int
	Age         int
	Luck        int
	SpeciesId   string
	tiles       map[string]Location
	terminal    bool
	markedTiles map[Location]Location
	roots       map[*growthRoot]struct{}
}

type Species struct {
	Color  int    `json:"color"`
	Source string `json:"source"`
	Author string `json:"author"`
	refCnt int
}

type gameState struct {
	World    [][]*Tile           `json:"world"`
	Species  map[string]*Species `json:"plants"`
	plants   []*Plant
	roots    map[*growthRoot]struct{}
	maxPlant int
}

type tileDiff struct {
	Loc  Location `json:"loc"`
	Tile Tile     `json:"tile"`
}

type spore struct {
	Location  Location `json:"location"`
	SpeciesId string   `json:"plantId"`
}

func (s *State) AddSpore(loc Location, plantId string) *spore {
	// TODO add in bounds checks
	s.plantAddRef(plantId)
	s.diff.Spores = append(s.diff.Spores, spore{loc, plantId})
	return &s.diff.Spores[len(s.diff.Spores)-1]
}

func (s *State) UpdateSpore(p *spore) bool {
	dx := rand.Intn(3) - 1
	dy := rand.Intn(2)
	p.Location.X += dx
	p.Location.Y += dy
	p.Location.X = (p.Location.X + s.Width()) % s.Width()

	s.Clamp(&p.Location)
	t := s.GetTile(p.Location)
	if t.Type == DirtTile {
		p.Location.Y--
		t = s.GetTile(p.Location)
		// dont plant if not on air tile
		if t.Type != AirTile {
			return true
		}

		plant := s.AddPlant(p.SpeciesId)
		s.AddGrowth(p.Location, plant, "")
		return true
	}
	return false
}

func (s *State) LandSpore(p *spore) {
	// find the spawn the spore
	for y := s.Height() - 1; y > 0; y-- {
		t := s.GetTile(Location{p.Location.X, y})
		if t.Type == AirTile {
			plant := s.AddPlant(p.SpeciesId)
			s.AddGrowth(p.Location, plant, "")
			break
		}
	}

	// remove the spore
	var i int
	for p := range s.diff.Spores {
		i = p
	}
	s.diff.Spores = append(s.diff.Spores[:i], s.diff.Spores[i+1:]...)
}

type diff struct {
	TileDiffs     []tileDiff          `json:"tileDiff"`
	NewPlants     map[string]*Species `json:"newPlants"`
	RemovedPlants []string            `json:"removedPlants"`
	Spores        []spore             `json:"spores"`
}

func (d *diff) isEmpty() bool {
	return len(d.TileDiffs) == 0 && len(d.NewPlants) == 0 && len(d.RemovedPlants) == 0 && len(d.Spores) == 0
}

type State struct {
	state gameState
	diff  diff
}

// Records a reference to a plant, causing the plant to be kept in the structure
func (s *State) plantAddRef(plantId string) {
	species, _ := s.GetSpecies(plantId)
	species.refCnt++
}

// Records a reference to a plant, causing the plant to be removed from the structure
func (s *State) plantRelease(plantId string) {
	plant, _ := s.GetSpecies(plantId)
	plant.refCnt--

	// If the reference count has reached zero, remove the plant from the thing
	if plant.refCnt <= 0 {
		s.diff.RemovedPlants = append(s.diff.RemovedPlants, plantId)
		delete(s.state.Species, plantId)
	}
}

func (s *State) Width() int {
	return len(s.state.World[0])
}

func (s *State) Height() int {
	return len(s.state.World)
}

func (s *State) GetSpecies(plantId string) (*Species, bool) {
	species, ok := s.state.Species[plantId]
	return species, ok
}

// Adds a species to the stateAndDiff, and returns the string key for the plant
// This plant is created with a refCnt of zero
// , but will not be dropped until
// its reference count hits zero again.
func (s *State) AddSpecies(color int, source string, author string) string {
	p := Species{color, source, author, 0}
	s.state.maxPlant += 1
	key := fmt.Sprintf("%d", s.state.maxPlant)
	s.diff.NewPlants[key] = &p
	s.state.Species[key] = &p
	return key
}

func (s *State) GetTile(loc Location) *Tile {
	return s.state.World[loc.Y][loc.X]
}

// Set the tile at a location to a new tile
func (s *State) SetTile(loc Location, new Tile) {
	// XXX FIXME - this is a hack because we get index errors so often here...
	s.Clamp(&loc)

	// Manage the addref and releases
	old := s.GetTile(loc)
	if old.Extra != nil {
		delete(old.Extra.Plant.tiles, loc.str())
	}
	if new.Extra != nil {
		new.Extra.Plant.tiles[loc.str()] = loc
	}

	// Actually update the tile and record the tilediffs
	*old = new
	s.diff.TileDiffs = append(s.diff.TileDiffs, tileDiff{loc, new})
}

func (s *State) ClearPlants() {
	for _, p := range s.state.plants {
		for r := range p.roots {
			s.HaltGrowth(r)
		}
		for _, t := range p.tiles {
			s.SetTile(t, Tile{AirTile, nil})
		}
	}

	s.state.plants = []*Plant{}
}

func (s *State) AddPlant(speciesId string) *Plant {
	s.plantAddRef(speciesId)
	plant := &Plant{100, 0, rand.Intn(6) + 1, speciesId, map[string]Location{}, false, nil, map[*growthRoot]struct{}{}}
	s.state.plants = append(s.state.plants, plant)
	return plant
}

func (s *State) AddGrowth(loc Location, plant *Plant, meta string) *growthRoot {
	if plant == nil {
		panic("crap")
	}
	species, _ := s.GetSpecies(plant.SpeciesId)

	// Create the sandbox node for the plant object
	node := sandbox.AddNode(species.Source, meta)

	// Create the root node for the object, and append it to the roots list
	root := growthRoot{plant.SpeciesId, loc, plant, node, nil}
	s.state.roots[&root] = struct{}{}
	plant.roots[&root] = struct{}{}

	isUnderground := false
	if s.GetTile(loc).Type == DirtTile {
		isUnderground = true
	}

	// Set the tile at the base of the plant to a plant tile
	s.SetTile(loc, Tile{PlantTile, &extraTileInfo{plant.SpeciesId, loc, isUnderground, plant}})

	// Return a reference to the root node we previously appended
	return &root
}

func (s *State) lowerToDirt(loc *Location) {
	var base int
	for y := 0; y < s.Height(); y++ {
		t := s.GetTile(Location{loc.X, y})
		if t.Type == DirtTile {
			base = y - 1
			break
		}
	}
	loc.Y = base
}

func (s *State) HaltGrowth(gr *growthRoot) {
	gr.node.Halt()
	delete(s.state.roots, gr)
}
<|endoftext|>


<commit_before>package zmq3_test

import (
	zmq "github.com/pebbe/zmq3"

	"fmt"
	"testing"
	"time"
)

func rep_socket_monitor(addr string, chMsg chan<- string) {

	defer close(chMsg)

	s, err := zmq.NewSocket(zmq.PAIR)
	if err != nil {
		chMsg <- fmt.Sprint("NewSocket:", err)
		return
	}
	defer func() {
		s.SetLinger(0)
		s.Close()
	}()

	err = s.Connect(addr)
	if err != nil {
		chMsg <- fmt.Sprint("s.Connect:", err)
		return
	}

	for {
		a, b, _, err := s.RecvEvent(0)
		if err != nil {
			chMsg <- fmt.Sprint("s.RecvEvent:", err)
			return
		}
		chMsg <- fmt.Sprint(a, " ", b)
		if a == zmq.EVENT_CLOSED {
			break
		}
	}
	chMsg <- "Done"
}

func TestSocketEvent(t *testing.T) {

	var rep *zmq.Socket
	defer func() {
		if rep != nil {
			rep.SetLinger(0)
			rep.Close()
		}
	}()

	// REP socket
	rep, err := zmq.NewSocket(zmq.REP)
	if err != nil {
		t.Fatal("NewSocket:", err)
	}

	// REP socket monitor, all events
	err = rep.Monitor("inproc://monitor.rep", zmq.EVENT_ALL)
	if err != nil {
		t.Fatal("rep.Monitor:", err)
	}
	chMsg := make(chan string, 10)
	go rep_socket_monitor("inproc://monitor.rep", chMsg)
	time.Sleep(time.Second)

	// Generate an event
	err = rep.Bind("tcp://*:9689")
	if err != nil {
		t.Fatal("rep.Bind:", err)
	}

	rep.Close()
	rep = nil

	expect := []string{
		"EVENT_LISTENING tcp://0.0.0.0:9689",
		"EVENT_CLOSED tcp://0.0.0.0:9689",
		"Done",
	}
	i := 0
	for msg := range chMsg {
		if i < len(expect) {
			if msg != expect[i] {
				t.Errorf("Expected message %q, got %q", expect[i], msg)
			}
			i++
		} else {
			t.Error("Unexpected message: %q", msg)
		}
	}
	for ; i < len(expect); i++ {
		t.Errorf("Expected message %q, got nothing", expect[i])
	}
}
<commit_msg>bugfix formatting in tests<commit_after>package zmq3_test

import (
	zmq "github.com/pebbe/zmq3"

	"fmt"
	"testing"
	"time"
)

func rep_socket_monitor(addr string, chMsg chan<- string) {

	defer close(chMsg)

	s, err := zmq.NewSocket(zmq.PAIR)
	if err != nil {
		chMsg <- fmt.Sprint("NewSocket:", err)
		return
	}
	defer func() {
		s.SetLinger(0)
		s.Close()
	}()

	err = s.Connect(addr)
	if err != nil {
		chMsg <- fmt.Sprint("s.Connect:", err)
		return
	}

	for {
		a, b, _, err := s.RecvEvent(0)
		if err != nil {
			chMsg <- fmt.Sprint("s.RecvEvent:", err)
			return
		}
		chMsg <- fmt.Sprint(a, " ", b)
		if a == zmq.EVENT_CLOSED {
			break
		}
	}
	chMsg <- "Done"
}

func TestSocketEvent(t *testing.T) {

	var rep *zmq.Socket
	defer func() {
		if rep != nil {
			rep.SetLinger(0)
			rep.Close()
		}
	}()

	// REP socket
	rep, err := zmq.NewSocket(zmq.REP)
	if err != nil {
		t.Fatal("NewSocket:", err)
	}

	// REP socket monitor, all events
	err = rep.Monitor("inproc://monitor.rep", zmq.EVENT_ALL)
	if err != nil {
		t.Fatal("rep.Monitor:", err)
	}
	chMsg := make(chan string, 10)
	go rep_socket_monitor("inproc://monitor.rep", chMsg)
	time.Sleep(time.Second)

	// Generate an event
	err = rep.Bind("tcp://*:9689")
	if err != nil {
		t.Fatal("rep.Bind:", err)
	}

	rep.Close()
	rep = nil

	expect := []string{
		"EVENT_LISTENING tcp://0.0.0.0:9689",
		"EVENT_CLOSED tcp://0.0.0.0:9689",
		"Done",
	}
	i := 0
	for msg := range chMsg {
		if i < len(expect) {
			if msg != expect[i] {
				t.Errorf("Expected message %q, got %q", expect[i], msg)
			}
			i++
		} else {
			t.Errorf("Unexpected message: %q", msg)
		}
	}
	for ; i < len(expect); i++ {
		t.Errorf("Expected message %q, got nothing", expect[i])
	}
}
<|endoftext|>


<commit_before>package cmd

// Version defines the current Pop version.
const Version = "v4.11.5"
<commit_msg>Bump version<commit_after>package cmd

// Version defines the current Pop version.
const Version = "v4.11.6"
<|endoftext|>


<commit_before>package cmd

// Version defines the current Pop version.
const Version = "v4.9.2"
<commit_msg>Reset version to development<commit_after>package cmd

// Version defines the current Pop version.
const Version = "development"
<|endoftext|>


<commit_before>package actors

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	acceptance "github.com/cloudfoundry/bosh-bootloader/acceptance-tests"
	"github.com/kr/pty"

	"github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

type BBL struct {
	stateDirectory    string
	pathToBBL         string
	configuration     acceptance.Config
	envID             string
	useBBLStateBucket bool
}

func NewBBL(stateDirectory string, pathToBBL string, configuration acceptance.Config, envIDSuffix string, useBBLStateBucket bool) BBL {
	envIDPrefix := os.Getenv("BBL_TEST_ENV_ID_PREFIX")
	if envIDPrefix == "" {
		envIDPrefix = "bbl-test"
	}

	return BBL{
		stateDirectory:    stateDirectory,
		pathToBBL:         pathToBBL,
		configuration:     configuration,
		envID:             fmt.Sprintf("%s-%s", envIDPrefix, envIDSuffix),
		useBBLStateBucket: useBBLStateBucket,
	}
}

func (b BBL) PredefinedEnvID() string {
	return b.envID
}

func (b BBL) Up(additionalArgs ...string) *gexec.Session {
	args := []string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"up",
	}

	args = append(args, additionalArgs...)

	return b.execute(args, os.Stdout, os.Stderr)
}

func (b BBL) Plan(additionalArgs ...string) *gexec.Session {
	args := []string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"plan",
	}

	args = append(args, additionalArgs...)

	return b.execute(args, os.Stdout, os.Stderr)
}

func (b BBL) Rotate() *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"rotate",
	}, os.Stdout, os.Stderr)
}

func (b BBL) VerifySSH(session *gexec.Session, ptmx *os.File) {
	time.Sleep(5 * time.Second)
	fmt.Fprintln(ptmx, "whoami | rev")
	Eventually(session.Out, 10).Should(gbytes.Say("xobpmuj")) // jumpbox in reverse
	fmt.Fprintln(ptmx, "exit 0")
	Eventually(session, 5).Should(gexec.Exit(0))
}

func (b BBL) JumpboxSSH(output io.Writer) *exec.Cmd {
	return b.interactiveExecute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"ssh",
		"--jumpbox",
	}, output, output, b.VerifySSH)
}

func (b BBL) DirectorSSH(output io.Writer) *exec.Cmd {
	return b.interactiveExecute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"ssh",
		"--director",
	}, output, output, b.VerifySSH)
}

func (b BBL) Destroy() *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"destroy",
		"--no-confirm",
	}, os.Stdout, os.Stderr)
}

func (b BBL) Down() *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"down",
		"--no-confirm",
	}, os.Stdout, os.Stderr)
}

func (b BBL) CleanupLeftovers(filter string) *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"cleanup-leftovers",
		"--filter", filter,
		"--no-confirm",
	}, os.Stdout, os.Stderr)
}

func (b BBL) Lbs() string {
	return b.fetchValue("lbs")
}

func (b BBL) DirectorUsername() string {
	return b.fetchValue("director-username")
}

func (b BBL) DirectorPassword() string {
	return b.fetchValue("director-password")
}

func (b BBL) DirectorAddress() string {
	return b.fetchValue("director-address")
}

func (b BBL) DirectorCACert() string {
	return b.fetchValue("director-ca-cert")
}

func (b BBL) JumpboxAddress() string {
	return b.fetchValue("jumpbox-address")
}

func (b BBL) SSHKey() string {
	return b.fetchValue("ssh-key")
}

func (b BBL) DirectorSSHKey() string {
	return b.fetchValue("director-ssh-key")
}

func (b BBL) EnvID() string {
	return b.fetchValue("env-id")
}

func (b BBL) PrintEnv() string {
	return b.fetchValue("print-env")
}

func (b BBL) LatestError() string {
	return b.fetchValue("latest-error")
}

func (b BBL) SaveDirectorCA() string {
	stdout := bytes.NewBuffer([]byte{})
	session := b.execute([]string{
		"--state-dir", b.stateDirectory,
		"director-ca-cert",
	}, stdout, os.Stderr)
	Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

	file, err := ioutil.TempFile("", "")
	defer file.Close()
	Expect(err).NotTo(HaveOccurred())

	file.Write(stdout.Bytes())

	return file.Name()
}

func (b BBL) ExportBoshAllProxy() string {
	lines := strings.Split(b.PrintEnv(), "\n")
	value := getExport("BOSH_ALL_PROXY", lines)
	os.Setenv("BOSH_ALL_PROXY", value)
	return value
}

func (b BBL) StartSSHTunnel() *gexec.Session {
	printEnvLines := strings.Split(b.PrintEnv(), "\n")
	os.Setenv("BOSH_ALL_PROXY", getExport("BOSH_ALL_PROXY", printEnvLines))

	var sshArgs []string
	for i := 0; i < len(printEnvLines); i++ {
		if strings.HasPrefix(printEnvLines[i], "ssh ") {
			sshCmd := strings.TrimPrefix(printEnvLines[i], "ssh ")
			sshCmd = strings.Replace(sshCmd, "$JUMPBOX_PRIVATE_KEY", getExport("JUMPBOX_PRIVATE_KEY", printEnvLines), -1)
			sshCmd = strings.Replace(sshCmd, "-f ", "", -1)
			sshArgs = strings.Split(sshCmd, " ")
		}
	}

	cmd := exec.Command("ssh", sshArgs...)
	sshSession, err := gexec.Start(cmd, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return sshSession
}

func getExport(keyName string, lines []string) string {
	for _, line := range lines {
		if strings.HasPrefix(line, fmt.Sprintf("export %s", keyName)) {
			parts := strings.Split(line, " ")
			keyValue := parts[1]
			keyValueParts := strings.Split(keyValue, "=")
			return strings.Join(keyValueParts[1:], "=")
		}
	}
	return ""
}

func (b BBL) fetchValue(value string) string {
	if b.useBBLStateBucket {
		return b.fetchValueFromRemoteBBLState(value)
	}
	return b.fetchValueFromLocalBBLState(value)
}

func (b BBL) fetchValueFromRemoteBBLState(value string) string {
	args := []string{
		"--name", b.envID,
		"--state-bucket", b.configuration.BBLStateBucket,
		value,
	}

	stdout := bytes.NewBuffer([]byte{})
	stderr := bytes.NewBuffer([]byte{})
	b.execute(args, stdout, stderr).Wait(30 * time.Second)

	return strings.TrimSpace(string(stdout.Bytes()))
}
func (b BBL) fetchValueFromLocalBBLState(value string) string {
	args := []string{
		"--state-dir", b.stateDirectory,
		value,
	}

	stdout := bytes.NewBuffer([]byte{})
	stderr := bytes.NewBuffer([]byte{})
	b.execute(args, stdout, stderr).Wait(30 * time.Second)

	return strings.TrimSpace(string(stdout.Bytes()))
}

func (b BBL) execute(args []string, stdout io.Writer, stderr io.Writer) *gexec.Session {
	cmd := exec.Command(b.pathToBBL, args...)
	session, err := gexec.Start(cmd, stdout, stderr)
	Expect(err).NotTo(HaveOccurred())

	return session
}

// partially cribbed from https://github.com/cloudfoundry/vizzini/blob/master/ssh_test.go#L473
func (b BBL) interactiveExecute(args []string, stdout io.Writer, stderr io.Writer, actions func(*gexec.Session, *os.File)) *exec.Cmd {
	cmd := exec.Command(b.pathToBBL, args...)

	ptmx, pts, err := pty.Open()
	Expect(err).NotTo(HaveOccurred())
	defer ptmx.Close()

	cmd.Stdin = pts
	cmd.Stdout = pts
	cmd.Stderr = pts

	cmd.SysProcAttr = &syscall.SysProcAttr{
		Setctty: true,
		Setsid:  true,
	}

	session, err := gexec.Start(cmd, stdout, stderr)
	Expect(err).NotTo(HaveOccurred())

	// Close our open reference to pts so that ptmx recieves EOF
	pts.Close()

	actions(session, ptmx)

	return cmd
}
<commit_msg>temporarily log stderr from remote state<commit_after>package actors

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	acceptance "github.com/cloudfoundry/bosh-bootloader/acceptance-tests"
	"github.com/kr/pty"

	"github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

type BBL struct {
	stateDirectory    string
	pathToBBL         string
	configuration     acceptance.Config
	envID             string
	useBBLStateBucket bool
}

func NewBBL(stateDirectory string, pathToBBL string, configuration acceptance.Config, envIDSuffix string, useBBLStateBucket bool) BBL {
	envIDPrefix := os.Getenv("BBL_TEST_ENV_ID_PREFIX")
	if envIDPrefix == "" {
		envIDPrefix = "bbl-test"
	}

	return BBL{
		stateDirectory:    stateDirectory,
		pathToBBL:         pathToBBL,
		configuration:     configuration,
		envID:             fmt.Sprintf("%s-%s", envIDPrefix, envIDSuffix),
		useBBLStateBucket: useBBLStateBucket,
	}
}

func (b BBL) PredefinedEnvID() string {
	return b.envID
}

func (b BBL) Up(additionalArgs ...string) *gexec.Session {
	args := []string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"up",
	}

	args = append(args, additionalArgs...)

	return b.execute(args, os.Stdout, os.Stderr)
}

func (b BBL) Plan(additionalArgs ...string) *gexec.Session {
	args := []string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"plan",
	}

	args = append(args, additionalArgs...)

	return b.execute(args, os.Stdout, os.Stderr)
}

func (b BBL) Rotate() *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"rotate",
	}, os.Stdout, os.Stderr)
}

func (b BBL) VerifySSH(session *gexec.Session, ptmx *os.File) {
	time.Sleep(5 * time.Second)
	fmt.Fprintln(ptmx, "whoami | rev")
	Eventually(session.Out, 10).Should(gbytes.Say("xobpmuj")) // jumpbox in reverse
	fmt.Fprintln(ptmx, "exit 0")
	Eventually(session, 5).Should(gexec.Exit(0))
}

func (b BBL) JumpboxSSH(output io.Writer) *exec.Cmd {
	return b.interactiveExecute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"ssh",
		"--jumpbox",
	}, output, output, b.VerifySSH)
}

func (b BBL) DirectorSSH(output io.Writer) *exec.Cmd {
	return b.interactiveExecute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"ssh",
		"--director",
	}, output, output, b.VerifySSH)
}

func (b BBL) Destroy() *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"destroy",
		"--no-confirm",
	}, os.Stdout, os.Stderr)
}

func (b BBL) Down() *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"--debug",
		"down",
		"--no-confirm",
	}, os.Stdout, os.Stderr)
}

func (b BBL) CleanupLeftovers(filter string) *gexec.Session {
	return b.execute([]string{
		"--state-dir", b.stateDirectory,
		"cleanup-leftovers",
		"--filter", filter,
		"--no-confirm",
	}, os.Stdout, os.Stderr)
}

func (b BBL) Lbs() string {
	return b.fetchValue("lbs")
}

func (b BBL) DirectorUsername() string {
	return b.fetchValue("director-username")
}

func (b BBL) DirectorPassword() string {
	return b.fetchValue("director-password")
}

func (b BBL) DirectorAddress() string {
	return b.fetchValue("director-address")
}

func (b BBL) DirectorCACert() string {
	return b.fetchValue("director-ca-cert")
}

func (b BBL) JumpboxAddress() string {
	return b.fetchValue("jumpbox-address")
}

func (b BBL) SSHKey() string {
	return b.fetchValue("ssh-key")
}

func (b BBL) DirectorSSHKey() string {
	return b.fetchValue("director-ssh-key")
}

func (b BBL) EnvID() string {
	return b.fetchValue("env-id")
}

func (b BBL) PrintEnv() string {
	return b.fetchValue("print-env")
}

func (b BBL) LatestError() string {
	return b.fetchValue("latest-error")
}

func (b BBL) SaveDirectorCA() string {
	stdout := bytes.NewBuffer([]byte{})
	session := b.execute([]string{
		"--state-dir", b.stateDirectory,
		"director-ca-cert",
	}, stdout, os.Stderr)
	Eventually(session, 10*time.Minute).Should(gexec.Exit(0))

	file, err := ioutil.TempFile("", "")
	defer file.Close()
	Expect(err).NotTo(HaveOccurred())

	file.Write(stdout.Bytes())

	return file.Name()
}

func (b BBL) ExportBoshAllProxy() string {
	lines := strings.Split(b.PrintEnv(), "\n")
	value := getExport("BOSH_ALL_PROXY", lines)
	os.Setenv("BOSH_ALL_PROXY", value)
	return value
}

func (b BBL) StartSSHTunnel() *gexec.Session {
	printEnvLines := strings.Split(b.PrintEnv(), "\n")
	os.Setenv("BOSH_ALL_PROXY", getExport("BOSH_ALL_PROXY", printEnvLines))

	var sshArgs []string
	for i := 0; i < len(printEnvLines); i++ {
		if strings.HasPrefix(printEnvLines[i], "ssh ") {
			sshCmd := strings.TrimPrefix(printEnvLines[i], "ssh ")
			sshCmd = strings.Replace(sshCmd, "$JUMPBOX_PRIVATE_KEY", getExport("JUMPBOX_PRIVATE_KEY", printEnvLines), -1)
			sshCmd = strings.Replace(sshCmd, "-f ", "", -1)
			sshArgs = strings.Split(sshCmd, " ")
		}
	}

	cmd := exec.Command("ssh", sshArgs...)
	sshSession, err := gexec.Start(cmd, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())

	return sshSession
}

func getExport(keyName string, lines []string) string {
	for _, line := range lines {
		if strings.HasPrefix(line, fmt.Sprintf("export %s", keyName)) {
			parts := strings.Split(line, " ")
			keyValue := parts[1]
			keyValueParts := strings.Split(keyValue, "=")
			return strings.Join(keyValueParts[1:], "=")
		}
	}
	return ""
}

func (b BBL) fetchValue(value string) string {
	if b.useBBLStateBucket {
		return b.fetchValueFromRemoteBBLState(value)
	}
	return b.fetchValueFromLocalBBLState(value)
}

func (b BBL) fetchValueFromRemoteBBLState(value string) string {
	args := []string{
		"--name", b.envID,
		"--state-bucket", b.configuration.BBLStateBucket,
		value,
	}

	stdout := bytes.NewBuffer([]byte{})
	stderr := bytes.NewBuffer([]byte{})
	b.execute(args, stdout, stderr).Wait(30 * time.Second)
	fmt.Println(stderr)

	return strings.TrimSpace(string(stdout.Bytes()))
}
func (b BBL) fetchValueFromLocalBBLState(value string) string {
	args := []string{
		"--state-dir", b.stateDirectory,
		value,
	}

	stdout := bytes.NewBuffer([]byte{})
	stderr := bytes.NewBuffer([]byte{})
	b.execute(args, stdout, stderr).Wait(30 * time.Second)

	return strings.TrimSpace(string(stdout.Bytes()))
}

func (b BBL) execute(args []string, stdout io.Writer, stderr io.Writer) *gexec.Session {
	cmd := exec.Command(b.pathToBBL, args...)
	session, err := gexec.Start(cmd, stdout, stderr)
	Expect(err).NotTo(HaveOccurred())

	return session
}

// partially cribbed from https://github.com/cloudfoundry/vizzini/blob/master/ssh_test.go#L473
func (b BBL) interactiveExecute(args []string, stdout io.Writer, stderr io.Writer, actions func(*gexec.Session, *os.File)) *exec.Cmd {
	cmd := exec.Command(b.pathToBBL, args...)

	ptmx, pts, err := pty.Open()
	Expect(err).NotTo(HaveOccurred())
	defer ptmx.Close()

	cmd.Stdin = pts
	cmd.Stdout = pts
	cmd.Stderr = pts

	cmd.SysProcAttr = &syscall.SysProcAttr{
		Setctty: true,
		Setsid:  true,
	}

	session, err := gexec.Start(cmd, stdout, stderr)
	Expect(err).NotTo(HaveOccurred())

	// Close our open reference to pts so that ptmx recieves EOF
	pts.Close()

	actions(session, ptmx)

	return cmd
}
<|endoftext|>


<commit_before>// 封装了tcp网关的操作
// 其实是实现了接口imodule
package gateway

import (
	"fmt"
	"lib/chanrpc"
	"lib/network"
	"lib/util"
)

// 定义网关结构体
type Gate struct {
	MaxConnNum       int               // 允许的最大的连接数
	PendingNum       int               // 允许的最大的客户端缓冲队列长度
	MaxMsgLen        uint32            // 允许的最大的消息长度
	ServerAddress    string            // tcp服务地址
	LenMsgLen        int               // tcp消息长度
	AgentChanRPC     *chanrpc.Server   // 用于路由的rpcserver
	MessageProcessor network.Processor // 用于消息体的处理
}

type agent struct {
	conn     network.Conn //客户端连接
	gate     *Gate        // 网关数据
	userData interface{}  // 用户数据
}

// tcp服务器
var tcpServer *network.TcpServer

/***************************实现imodule接口*******************************/

// 启动tcp网关
func (gate *Gate) Run(chClose chan bool) {
	tcpServer.Start()
	<-chClose
	tcpServer.Close()
}

// 初始化
func (gate *Gate) OnInit() {
	// FIXME 这里没有对gate的内容做验证
	if gate == nil {
		fmt.Println("tcp_gateway run failed, because gate is nil")
		return
	}
	tcpServer = new(network.TcpServer)
	tcpServer.ServerAddress = gate.ServerAddress
	tcpServer.MaxConnNum = gate.MaxConnNum
	tcpServer.PendingNum = gate.PendingNum
	tcpServer.Agent = func(conn *network.Conn) network.Iagent {
		fmt.Println("NewAgent:", util.GetPid())
		arg := &agent{conn: *conn, gate: gate}
		if gate.AgentChanRPC != nil {
			gate.AgentChanRPC.Go("NewAgent", arg)
		}
		return arg
	}
}

// 资源回收
func (gate *Gate) OnDestroy() {
	fmt.Println("tcp网关销毁中")
}

/****************************实现了Iagent接口**********************************/

func (agent *agent) Run() {
	fmt.Println("客户端代理执行的run函数")
	if agent.gate == nil {
		fmt.Println("Run params is nil")
		return
	}
	for {
		// 读取消息
		msg, err := agent.conn.ReadMsg()
		if err != nil {
			fmt.Println(err)
			break
		}
		// 反序列化
		realMsg, errs := agent.gate.MessageProcessor.Deserialize(msg)
		if errs != nil {
			fmt.Println(errs)
			break
		}
		// 消息路由
		if err := agent.gate.MessageProcessor.Route(realMsg, agent); err != nil {
			fmt.Println("msg route err:", err)
			break
		}

	}
}

func (agent *agent) OnClose() {

}
<commit_msg>update tcp_gateway<commit_after>// 封装了tcp网关的操作
// 其实是实现了接口imodule
package gateway

import (
	"fmt"
	"lib/chanrpc"
	"lib/network"
	"lib/util"
)

// 定义网关结构体
type Gate struct {
	MaxConnNum       int               // 允许的最大的连接数
	PendingNum       int               // 允许的最大的客户端缓冲队列长度
	MaxMsgLen        uint32            // 允许的最大的消息长度
	ServerAddress    string            // tcp服务地址
	LenMsgLen        int               // tcp消息长度
	AgentChanRPC     *chanrpc.Server   // 用于路由的rpcserver
	MessageProcessor network.Processor // 用于消息体的处理
}

type agent struct {
	conn     network.Conn //客户端连接
	gate     *Gate        // 网关数据
	userData interface{}  // 用户数据
}

// tcp服务器
var tcpServer *network.TcpServer

/***************************实现imodule接口*******************************/

// 启动tcp网关
func (gate *Gate) Run(chClose chan bool) {
	tcpServer.Start()
	<-chClose
	tcpServer.Close()
}

// 初始化
func (gate *Gate) OnInit() {
	// FIXME 这里没有对gate的内容做验证
	if gate == nil {
		fmt.Println("tcp_gateway run failed, because gate is nil")
		return
	}
	tcpServer = new(network.TcpServer)
	tcpServer.ServerAddress = gate.ServerAddress
	tcpServer.MaxConnNum = gate.MaxConnNum
	tcpServer.PendingNum = gate.PendingNum
	tcpServer.Agent = func(conn *network.Conn) network.Iagent {
		fmt.Println("NewAgent:", util.GetPid())
		arg := &agent{conn: *conn, gate: gate}
		if gate.AgentChanRPC != nil {
			gate.AgentChanRPC.Go("NewAgent", arg)
		}
		return arg
	}
}

// 资源回收
func (gate *Gate) OnDestroy() {
	fmt.Println("tcp网关销毁中")
}

/****************************实现了Iagent接口**********************************/

func (agent *agent) Run() {
	fmt.Println("客户端代理执行的run函数")
	if agent.gate == nil {
		fmt.Println("Run params is nil")
		return
	}
	for {
		// 读取消息
		msg, err := agent.conn.ReadMsg()
		if err != nil {
			fmt.Println(err)
			break
		}
		// 反序列化
		realMsg, errs := agent.gate.MessageProcessor.Deserialize(msg)
		if errs != nil {
			fmt.Println(errs)
			break
		}
		// 消息路由
		if err := agent.gate.MessageProcessor.Route(realMsg, agent); err != nil {
			fmt.Println("msg route err:", err)
			break
		}
	}
}

func (agent *agent) OnClose() {

}
<|endoftext|>