<commit_before>package game

import (
	"github.com/ghthor/engine/rpg2d/coord"
	"github.com/ghthor/engine/rpg2d/quad"
	"github.com/ghthor/engine/sim/stime"

	"github.com/ghthor/gospec"
	. "github.com/ghthor/gospec"
)

type spec_2moving struct {
	spec         string
	paths        []coord.PathAction
	expectations func(spec_2moving, actorIndex, gospec.Context)
}

func (t spec_2moving) runSpec(c gospec.Context) {
	pa0 := t.paths[0]
	pa1 := t.paths[1]

	index := actorIndex{
		0: &actor{
			actorEntity: actorEntity{
				id: 0,

				cell:   pa0.Orig,
				facing: pa0.Direction(),
			},
		},

		1: &actor{
			actorEntity: actorEntity{
				id: 1,

				cell:   pa1.Orig,
				facing: pa1.Direction(),
			},
		},
	}

	index[0].applyPathAction(&pa0)
	index[1].applyPathAction(&pa1)

	phase := narrowPhase{index}
	testCases := []struct {
		spec string
		cgrp quad.CollisionGroup
	}{{
		"AB", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[0].Entity(),
			index[1].Entity(),
		}),
	}, {
		"BA", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[1].Entity(),
			index[0].Entity(),
		}),
	}}

	c.Specify(t.spec, func() {
		for _, testCase := range testCases {
			c.Specify(testCase.spec, func() {
				stillExisting, removed := phase.ResolveCollisions(&testCase.cgrp, 0)
				c.Assume(len(stillExisting), Equals, 2)
				c.Assume(len(removed), Equals, 0)

				t.expectations(t, index, c)
			})
		}
	})
}

type spec_1move_1stand struct {
	spec string

	// entity 0
	path coord.PathAction

	// entity 1
	cell   coord.Cell
	facing coord.Direction

	expectations func(spec_1move_1stand, actorIndex, gospec.Context)
}

func (t spec_1move_1stand) runSpec(c gospec.Context) {
	index := actorIndex{
		0: &actor{
			actorEntity: actorEntity{
				id:     0,
				cell:   t.path.Orig,
				facing: t.path.Direction(),
			},
		},

		1: &actor{
			actorEntity: actorEntity{
				id:     1,
				cell:   t.cell,
				facing: t.facing,
			},
		},
	}

	index[0].applyPathAction(&t.path)

	phase := narrowPhase{index}
	testCases := []struct {
		spec string
		cgrp quad.CollisionGroup
	}{{
		"AB", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[0].Entity(),
			index[1].Entity(),
		}),
	}, {
		"BA", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[1].Entity(),
			index[0].Entity(),
		}),
	}}

	c.Specify(t.spec, func() {
		for _, testCase := range testCases {
			c.Specify(testCase.spec, func() {
				stillExisting, removed := phase.ResolveCollisions(&testCase.cgrp, 0)
				c.Assume(len(stillExisting), Equals, 2)
				c.Assume(len(removed), Equals, 0)

				t.expectations(t, index, c)
			})
		}
	})
}

func DescribeCollision(c gospec.Context) {
	cell := func(x, y int) coord.Cell { return coord.Cell{x, y} }
	pa := func(start, speed int64, origin, dest coord.Cell) coord.PathAction {
		return coord.PathAction{
			Span: stime.NewSpan(stime.Time(start), stime.Time(start+speed)),
			Orig: origin,
			Dest: dest,
		}
	}

	c.Specify("a collision between", func() {
		c.Specify("2 actors", func() {

			c.Specify("that are both moving", func() {
				testCases := []spec_2moving{{
					spec: "in the same direction",
					paths: []coord.PathAction{
						pa(0, 5, cell(0, 0), cell(0, 1)),
						pa(0, 10, cell(0, 1), cell(0, 2)),
					},
					expectations: func(testCase spec_2moving, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
						c.Expect(*index[1].pathAction, Equals, testCase.paths[1])
					},
				}, {
					spec: "head to head",
					paths: []coord.PathAction{
						pa(0, 10, cell(0, 0), cell(0, 1)),
						pa(0, 10, cell(0, 1), cell(0, 0)),
					},
					expectations: func(testCase spec_2moving, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
						c.Expect(index[1].pathAction, IsNil)
					},
				}}

				for _, testCase := range testCases {
					testCase.runSpec(c)
				}
			})

			c.Specify("where 1 is moving and 1 is standing still,", func() {
				testCases := []spec_1move_1stand{{
					"moving into stationary from the side",

					// entity 0
					pa(0, 10, cell(0, 0), cell(1, 0)),

					// entity 1
					cell(1, 0),
					coord.South,

					func(t spec_1move_1stand, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
					},
				}, {
					"moving into stationary from behind",

					// entity 0
					pa(0, 10, cell(0, 0), cell(1, 0)),

					// entity 1
					cell(1, 0),
					coord.East,

					func(t spec_1move_1stand, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
					},
				}, {
					"moving into stationary from in front",

					// entity 0
					pa(0, 10, cell(0, 0), cell(1, 0)),

					// entity 1
					cell(1, 0),
					coord.West,

					func(t spec_1move_1stand, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
					},
				}}

				for _, testCase := range testCases {
					testCase.runSpec(c)
				}
			})
		})
	})
}
<commit_msg>[game] factor in the call to specify<commit_after>package game

import (
	"github.com/ghthor/engine/rpg2d/coord"
	"github.com/ghthor/engine/rpg2d/quad"
	"github.com/ghthor/engine/sim/stime"

	"github.com/ghthor/gospec"
	. "github.com/ghthor/gospec"
)

type spec_2moving struct {
	spec         string
	paths        []coord.PathAction
	expectations func(spec_2moving, actorIndex, gospec.Context)
}

func (t spec_2moving) runSpec(c gospec.Context) {
	pa0 := t.paths[0]
	pa1 := t.paths[1]

	index := actorIndex{
		0: &actor{
			actorEntity: actorEntity{
				id: 0,

				cell:   pa0.Orig,
				facing: pa0.Direction(),
			},
		},

		1: &actor{
			actorEntity: actorEntity{
				id: 1,

				cell:   pa1.Orig,
				facing: pa1.Direction(),
			},
		},
	}

	index[0].applyPathAction(&pa0)
	index[1].applyPathAction(&pa1)

	phase := narrowPhase{index}
	testCases := []struct {
		spec string
		cgrp quad.CollisionGroup
	}{{
		"AB", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[0].Entity(),
			index[1].Entity(),
		}),
	}, {
		"BA", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[1].Entity(),
			index[0].Entity(),
		}),
	}}

	for _, testCase := range testCases {
		c.Specify(testCase.spec, func() {
			stillExisting, removed := phase.ResolveCollisions(&testCase.cgrp, 0)
			c.Assume(len(stillExisting), Equals, 2)
			c.Assume(len(removed), Equals, 0)

			t.expectations(t, index, c)
		})
	}
}

type spec_1move_1stand struct {
	spec string

	// entity 0
	path coord.PathAction

	// entity 1
	cell   coord.Cell
	facing coord.Direction

	expectations func(spec_1move_1stand, actorIndex, gospec.Context)
}

func (t spec_1move_1stand) runSpec(c gospec.Context) {
	index := actorIndex{
		0: &actor{
			actorEntity: actorEntity{
				id:     0,
				cell:   t.path.Orig,
				facing: t.path.Direction(),
			},
		},

		1: &actor{
			actorEntity: actorEntity{
				id:     1,
				cell:   t.cell,
				facing: t.facing,
			},
		},
	}

	index[0].applyPathAction(&t.path)

	phase := narrowPhase{index}
	testCases := []struct {
		spec string
		cgrp quad.CollisionGroup
	}{{
		"AB", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[0].Entity(),
			index[1].Entity(),
		}),
	}, {
		"BA", quad.CollisionGroup{}.AddCollision(quad.Collision{
			index[1].Entity(),
			index[0].Entity(),
		}),
	}}

	c.Specify(t.spec, func() {
		for _, testCase := range testCases {
			c.Specify(testCase.spec, func() {
				stillExisting, removed := phase.ResolveCollisions(&testCase.cgrp, 0)
				c.Assume(len(stillExisting), Equals, 2)
				c.Assume(len(removed), Equals, 0)

				t.expectations(t, index, c)
			})
		}
	})
}

func DescribeCollision(c gospec.Context) {
	cell := func(x, y int) coord.Cell { return coord.Cell{x, y} }
	pa := func(start, speed int64, origin, dest coord.Cell) coord.PathAction {
		return coord.PathAction{
			Span: stime.NewSpan(stime.Time(start), stime.Time(start+speed)),
			Orig: origin,
			Dest: dest,
		}
	}

	c.Specify("a collision between", func() {
		c.Specify("2 actors", func() {

			c.Specify("that are both moving", func() {
				testCases := []spec_2moving{{
					spec: "in the same direction",
					paths: []coord.PathAction{
						pa(0, 5, cell(0, 0), cell(0, 1)),
						pa(0, 10, cell(0, 1), cell(0, 2)),
					},
					expectations: func(testCase spec_2moving, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
						c.Expect(*index[1].pathAction, Equals, testCase.paths[1])
					},
				}, {
					spec: "head to head",
					paths: []coord.PathAction{
						pa(0, 10, cell(0, 0), cell(0, 1)),
						pa(0, 10, cell(0, 1), cell(0, 0)),
					},
					expectations: func(testCase spec_2moving, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
						c.Expect(index[1].pathAction, IsNil)
					},
				}}

				for _, testCase := range testCases {
					c.Specify(testCase.spec, func() {
						testCase.runSpec(c)
					})
				}
			})

			c.Specify("where 1 is moving and 1 is standing still,", func() {
				testCases := []spec_1move_1stand{{
					"moving into stationary from the side",

					// entity 0
					pa(0, 10, cell(0, 0), cell(1, 0)),

					// entity 1
					cell(1, 0),
					coord.South,

					func(t spec_1move_1stand, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
					},
				}, {
					"moving into stationary from behind",

					// entity 0
					pa(0, 10, cell(0, 0), cell(1, 0)),

					// entity 1
					cell(1, 0),
					coord.East,

					func(t spec_1move_1stand, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
					},
				}, {
					"moving into stationary from in front",

					// entity 0
					pa(0, 10, cell(0, 0), cell(1, 0)),

					// entity 1
					cell(1, 0),
					coord.West,

					func(t spec_1move_1stand, index actorIndex, c gospec.Context) {
						c.Expect(index[0].pathAction, IsNil)
					},
				}}

				for _, testCase := range testCases {
					testCase.runSpec(c)
				}
			})
		})
	})
}
<|endoftext|>


<commit_before>package boardgame

import (
	"errors"
)

//GameDelegate is the place that various parts of the game lifecycle can be
//modified to support this particular game.
type GameDelegate interface {

	//Name is a string that defines the type of game this is. The name should
	//be unique and compact. Good examples are "tictactoe", "blackjack". Once
	//configured, names should never change over the lifetime of the gametype,
	//since it will be persisted in storage. Subclasses should override this.
	Name() string

	//DisplayName is a string that defines the type of game this is in a way
	//appropriate for humans. The name should be unique but human readable. It
	//is purely for human consumption, and may change over time with no
	//adverse effects. Good examples are "Tic Tac Toe", "Blackjack".
	//Subclasses should override this.
	DisplayName() string

	//DistributeComponentToStarterStack is called during set up to establish
	//the Deck/Stack invariant that every component in the chest is placed in
	//precisely one Stack. Game will call this on each component in the Chest
	//in order. This is where the logic goes to make sure each Component goes
	//into its correct starter stack. As long as you put each component into a
	//Stack, the invariant will be met at the end of SetUp. If any errors are
	//returned SetUp fails. Unlike after the game has been SetUp, you can
	//modify payload directly.
	DistributeComponentToStarterStack(state *State, c *Component) error

	//BeginSetup is a chance to modify the initial state object *before* the
	//components are distributed to it. This is a good place to configure
	//state that will be necessary for you to make the right decisions in
	//DistributeComponentToStarterStack.
	BeginSetUp(state *State)

	//FinishSetUp is called during game.SetUp, *after* components have been
	//distributed to their StarterStack. This is the last chance to modify the
	//state before the game's initial state is considered final. For example,
	//if you have a card game this is where you'd make sure the starter draw
	//stacks are shuffled.
	FinishSetUp(state *State)

	//CheckGameFinished should return true if the game is finished, and who
	//the winners are. Called after every move is applied.
	CheckGameFinished(state *State) (finished bool, winners []int)

	//ProposeFixUpMove is called after a move has been applied. It may return
	//a FixUp move, which will be applied before any other moves are applied.
	//If it returns nil, we may take the next move off of the queue. FixUp
	//moves are useful for things like shuffling a discard deck back into a
	//draw deck, or other moves that are necessary to get the GameState back
	//into reasonable shape.
	ProposeFixUpMove(state *State) Move

	//DefaultNumPlayers returns the number of users that this game defaults to.
	//For example, for tictactoe, it will be 2. If 0 is provided to
	//game.SetUp(), we wil use this value insteadp.
	DefaultNumPlayers() int

	//LegalNumPlayers will be consulted when a new game is created. It should
	//return true if the given number of players is legal, and false
	//otherwise. If this returns false, the game's SetUp will fail. Game.SetUp
	//will automatically reject a numPlayers that does not result in at least
	//one player existing.
	LegalNumPlayers(numPlayers int) bool

	//EmptyGameState and EmptyPlayerState are called to get an instantiation
	//of the concrete game/player structs that your package defines. This is
	//used both to create the initial state, but also to inflate states from
	//the database. These methods should always return the underlying same
	//type of struct when called. This means that if different players have
	//very different roles in a game, there might be many properties that are
	//not in use for any given player. The simple properties (ints, bools,
	//strings) should all be their zero-value. Importantly, all Stacks should
	//be non- nil, because an initialized struct contains information about
	//things like MaxSize, Size, and a reference to the deck they are
	//affiliated with. Game methods that use these will fail if the State
	//objects return have uninitialized stacks. Since these two methods are
	//always required and always specific to each game type,
	//DefaultGameDelegate does not implement them, as an extra reminder that
	//you must implement them yourself.
	EmptyGameState() GameState
	EmptyPlayerState(playerIndex int) PlayerState

	//StateSanitizationPolicy returns the policy for sanitizing states in this
	//game. The policy should not change over time. See StatePolicy for more
	//on how sanitization policies are calculated and applied.
	StateSanitizationPolicy() *StatePolicy

	//Diagram should return a basic debug rendering of state in multi-line
	//ascii art. Useful for debugging. State.Diagram() will reach out to this
	//method.
	Diagram(s *State) string

	//SetManager configures which manager this delegate is in use with. A
	//given delegate can only be used by a single manager at a time.
	SetManager(manager *GameManager)

	//Manager returns the Manager that was set on this delegate.
	Manager() *GameManager
}

//DefaultGameDelegate is a struct that implements stubs for all of
//GameDelegate's methods. This makes it easy to override just one or two
//methods by creating your own struct that anonymously embeds this one. You
//almost certainly want to override StartingState.
type DefaultGameDelegate struct {
	manager *GameManager
}

func (d *DefaultGameDelegate) Diagram(state *State) string {
	return "This should be overriden to render a reasonable state here"
}

func (d *DefaultGameDelegate) Name() string {
	return "default"
}

func (d *DefaultGameDelegate) DisplayName() string {
	return "Default Game"
}

func (d *DefaultGameDelegate) Manager() *GameManager {
	return d.manager
}

func (d *DefaultGameDelegate) SetManager(manager *GameManager) {
	d.manager = manager
}

//The Default ProposeFixUpMove runs through all moves in FixUpMoves, in order,
//and returns the first one that is legal at the current state. In many cases,
//this behavior should be suficient and need not be overwritten. Be extra sure
//that your FixUpMoves have a conservative Legal function, otherwise you could
//get a panic from applying too many FixUp moves.
func (d *DefaultGameDelegate) ProposeFixUpMove(state *State) Move {
	for _, move := range d.Manager().FixUpMoves() {
		move.DefaultsForState(state)
		if err := move.Legal(state); err == nil {
			//Found it!
			return move
		}
	}
	//No moves apply now.
	return nil
}

func (d *DefaultGameDelegate) DistributeComponentToStarterStack(state *State, c *Component) error {
	//The stub returns an error, because if this is called that means there
	//was a component in the deck. And if we didn't store it in a stack, then
	//we are in violation of the invariant.
	return errors.New("DistributeComponentToStarterStack was called, but the component was not stored in a stack")
}

func (d *DefaultGameDelegate) StateSanitizationPolicy() *StatePolicy {
	return nil
}

func (d *DefaultGameDelegate) BeginSetUp(stae *State) {
	//Don't need to do anything by default
}

func (d *DefaultGameDelegate) FinishSetUp(state *State) {
	//Don't need to do anything by default
}

func (d *DefaultGameDelegate) CheckGameFinished(state *State) (finished bool, winners []int) {
	return false, nil
}

func (d *DefaultGameDelegate) DefaultNumPlayers() int {
	return 2
}

func (d *DefaultGameDelegate) LegalNumPlayers(numPlayers int) bool {
	if numPlayers > 0 && numPlayers <= 10 {
		return true
	}
	return false
}
<commit_msg>Updated a comment on an invariant to maintain. Fixes #96.<commit_after>package boardgame

import (
	"errors"
)

//GameDelegate is the place that various parts of the game lifecycle can be
//modified to support this particular game.
type GameDelegate interface {

	//Name is a string that defines the type of game this is. The name should
	//be unique and compact. Good examples are "tictactoe", "blackjack". Once
	//configured, names should never change over the lifetime of the gametype,
	//since it will be persisted in storage. Subclasses should override this.
	Name() string

	//DisplayName is a string that defines the type of game this is in a way
	//appropriate for humans. The name should be unique but human readable. It
	//is purely for human consumption, and may change over time with no
	//adverse effects. Good examples are "Tic Tac Toe", "Blackjack".
	//Subclasses should override this.
	DisplayName() string

	//DistributeComponentToStarterStack is called during set up to establish
	//the Deck/Stack invariant that every component in the chest is placed in
	//precisely one Stack. Game will call this on each component in the Chest
	//in order. This is where the logic goes to make sure each Component goes
	//into its correct starter stack. As long as you put each component into a
	//Stack, the invariant will be met at the end of SetUp. If any errors are
	//returned SetUp fails. Unlike after the game has been SetUp, you can
	//modify payload directly.
	DistributeComponentToStarterStack(state *State, c *Component) error

	//BeginSetup is a chance to modify the initial state object *before* the
	//components are distributed to it. This is a good place to configure
	//state that will be necessary for you to make the right decisions in
	//DistributeComponentToStarterStack.
	BeginSetUp(state *State)

	//FinishSetUp is called during game.SetUp, *after* components have been
	//distributed to their StarterStack. This is the last chance to modify the
	//state before the game's initial state is considered final. For example,
	//if you have a card game this is where you'd make sure the starter draw
	//stacks are shuffled.
	FinishSetUp(state *State)

	//CheckGameFinished should return true if the game is finished, and who
	//the winners are. Called after every move is applied.
	CheckGameFinished(state *State) (finished bool, winners []int)

	//ProposeFixUpMove is called after a move has been applied. It may return
	//a FixUp move, which will be applied before any other moves are applied.
	//If it returns nil, we may take the next move off of the queue. FixUp
	//moves are useful for things like shuffling a discard deck back into a
	//draw deck, or other moves that are necessary to get the GameState back
	//into reasonable shape.
	ProposeFixUpMove(state *State) Move

	//DefaultNumPlayers returns the number of users that this game defaults to.
	//For example, for tictactoe, it will be 2. If 0 is provided to
	//game.SetUp(), we wil use this value insteadp.
	DefaultNumPlayers() int

	//LegalNumPlayers will be consulted when a new game is created. It should
	//return true if the given number of players is legal, and false
	//otherwise. If this returns false, the game's SetUp will fail. Game.SetUp
	//will automatically reject a numPlayers that does not result in at least
	//one player existing.
	LegalNumPlayers(numPlayers int) bool

	//EmptyGameState and EmptyPlayerState are called to get an instantiation
	//of the concrete game/player structs that your package defines. This is
	//used both to create the initial state, but also to inflate states from
	//the database. These methods should always return the underlying same
	//type of struct when called. This means that if different players have
	//very different roles in a game, there might be many properties that are
	//not in use for any given player. The simple properties (ints, bools,
	//strings) should all be their zero-value. Importantly, all Stacks should
	//be non- nil, because an initialized struct contains information about
	//things like MaxSize, Size, and a reference to the deck they are
	//affiliated with. Game methods that use these will fail if the State
	//objects return have uninitialized stacks. Since these two methods are
	//always required and always specific to each game type,
	//DefaultGameDelegate does not implement them, as an extra reminder that
	//you must implement them yourself.
	EmptyGameState() GameState
	//EmptyPlayerState is similar to EmptyGameState, but playerIndex is the
	//value that this PlayerState must return when its PlayerIndex() is
	//called.
	EmptyPlayerState(playerIndex int) PlayerState

	//StateSanitizationPolicy returns the policy for sanitizing states in this
	//game. The policy should not change over time. See StatePolicy for more
	//on how sanitization policies are calculated and applied.
	StateSanitizationPolicy() *StatePolicy

	//Diagram should return a basic debug rendering of state in multi-line
	//ascii art. Useful for debugging. State.Diagram() will reach out to this
	//method.
	Diagram(s *State) string

	//SetManager configures which manager this delegate is in use with. A
	//given delegate can only be used by a single manager at a time.
	SetManager(manager *GameManager)

	//Manager returns the Manager that was set on this delegate.
	Manager() *GameManager
}

//DefaultGameDelegate is a struct that implements stubs for all of
//GameDelegate's methods. This makes it easy to override just one or two
//methods by creating your own struct that anonymously embeds this one. You
//almost certainly want to override StartingState.
type DefaultGameDelegate struct {
	manager *GameManager
}

func (d *DefaultGameDelegate) Diagram(state *State) string {
	return "This should be overriden to render a reasonable state here"
}

func (d *DefaultGameDelegate) Name() string {
	return "default"
}

func (d *DefaultGameDelegate) DisplayName() string {
	return "Default Game"
}

func (d *DefaultGameDelegate) Manager() *GameManager {
	return d.manager
}

func (d *DefaultGameDelegate) SetManager(manager *GameManager) {
	d.manager = manager
}

//The Default ProposeFixUpMove runs through all moves in FixUpMoves, in order,
//and returns the first one that is legal at the current state. In many cases,
//this behavior should be suficient and need not be overwritten. Be extra sure
//that your FixUpMoves have a conservative Legal function, otherwise you could
//get a panic from applying too many FixUp moves.
func (d *DefaultGameDelegate) ProposeFixUpMove(state *State) Move {
	for _, move := range d.Manager().FixUpMoves() {
		move.DefaultsForState(state)
		if err := move.Legal(state); err == nil {
			//Found it!
			return move
		}
	}
	//No moves apply now.
	return nil
}

func (d *DefaultGameDelegate) DistributeComponentToStarterStack(state *State, c *Component) error {
	//The stub returns an error, because if this is called that means there
	//was a component in the deck. And if we didn't store it in a stack, then
	//we are in violation of the invariant.
	return errors.New("DistributeComponentToStarterStack was called, but the component was not stored in a stack")
}

func (d *DefaultGameDelegate) StateSanitizationPolicy() *StatePolicy {
	return nil
}

func (d *DefaultGameDelegate) BeginSetUp(stae *State) {
	//Don't need to do anything by default
}

func (d *DefaultGameDelegate) FinishSetUp(state *State) {
	//Don't need to do anything by default
}

func (d *DefaultGameDelegate) CheckGameFinished(state *State) (finished bool, winners []int) {
	return false, nil
}

func (d *DefaultGameDelegate) DefaultNumPlayers() int {
	return 2
}

func (d *DefaultGameDelegate) LegalNumPlayers(numPlayers int) bool {
	if numPlayers > 0 && numPlayers <= 10 {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package gaurun

import (
	"net"
	"net/http"
	"time"

	"github.com/mercari/gcm"
)

func keepAliveInterval(keepAliveTimeout int) int {
	const minInterval = 30
	if keepAliveTimeout <= minInterval {
		return keepAliveTimeout
	}
	result := keepAliveTimeout / 3
	if result < minInterval {
		return minInterval
	}
	return result
}

func InitHttpClient() error {
	TransportGCM := &http.Transport{
		MaxIdleConnsPerHost: ConfGaurun.Android.KeepAliveConns,
		Dial: (&net.Dialer{
			Timeout:   time.Duration(ConfGaurun.Android.Timeout) * time.Second,
			KeepAlive: keepAliveInterval(ConfGaurun.Android.Timeout),
		}).Dial,
		IdleConnTimeout: time.Duration(ConfGaurun.Android.KeepAliveTimeout) * time.Second,
	}
	GCMClient = &gcm.Sender{
		ApiKey: ConfGaurun.Android.ApiKey,
		Http: &http.Client{
			Transport: TransportGCM,
			Timeout:   time.Duration(ConfGaurun.Android.Timeout) * time.Second,
		},
	}

	var err error
	APNSClient, err = NewApnsClientHttp2(
		ConfGaurun.Ios.PemCertPath,
		ConfGaurun.Ios.PemKeyPath,
	)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>fixed previous mistaken commit.<commit_after>package gaurun

import (
	"net"
	"net/http"
	"time"

	"github.com/mercari/gcm"
)

func keepAliveInterval(keepAliveTimeout int) int {
	const minInterval = 30
	if keepAliveTimeout <= minInterval {
		return keepAliveTimeout
	}
	result := keepAliveTimeout / 3
	if result < minInterval {
		return minInterval
	}
	return result
}

func InitHttpClient() error {
	TransportGCM := &http.Transport{
		MaxIdleConnsPerHost: ConfGaurun.Android.KeepAliveConns,
		Dial: (&net.Dialer{
			Timeout:   time.Duration(ConfGaurun.Android.Timeout) * time.Second,
			KeepAlive: keepAliveInterval(ConfGaurun.Android.KeepAliveTimeout),
		}).Dial,
		IdleConnTimeout: time.Duration(ConfGaurun.Android.KeepAliveTimeout) * time.Second,
	}
	GCMClient = &gcm.Sender{
		ApiKey: ConfGaurun.Android.ApiKey,
		Http: &http.Client{
			Transport: TransportGCM,
			Timeout:   time.Duration(ConfGaurun.Android.Timeout) * time.Second,
		},
	}

	var err error
	APNSClient, err = NewApnsClientHttp2(
		ConfGaurun.Ios.PemCertPath,
		ConfGaurun.Ios.PemKeyPath,
	)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

// Restrict this test to builds that specify the tag 'integration'.
// +build integration

package gcs_test

import (
	"testing"

	. "github.com/jacobsa/ogletest"
)

func TestConn(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ConnTest struct {
}

func init() { RegisterTestSuite(&ConnTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ConnTest) BadCredentials() {
	AssertTrue(false, "TODO")
}
<commit_msg>ConnTest.BadCredentials<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.

// Restrict this test to builds that specify the tag 'integration'.
// +build integration

package gcs_test

import (
	"testing"

	"golang.org/x/net/context"
	"golang.org/x/oauth2/google"

	"github.com/jacobsa/gcloud/gcs"
	. "github.com/jacobsa/ogletest"
)

func TestConn(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ConnTest struct {
}

func init() { RegisterTestSuite(&ConnTest{}) }

////////////////////////////////////////////////////////////////////////
// Tests
////////////////////////////////////////////////////////////////////////

func (t *ConnTest) BadCredentials() {
	var err error

	// Set up a token source.
	const scope = gcs.Scope_FullControl
	tokenSrc, err := google.DefaultTokenSource(context.Background(), scope)
	AssertEq(nil, err)

	// Use that to create a GCS connection, enabling retry if requested.
	cfg := &gcs.ConnConfig{
		TokenSource: tokenSrc,
	}

	conn, err := gcs.NewConn(cfg)
	AssertEq(nil, err)

	// Attempt to open a bucket to which we don't have access.
	_, err = conn.OpenBucket("golang")
	ExpectThat(err, Error(HasSubstr("TODO")))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"html/template"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/lemmi/ghfs"
	g "github.com/lemmi/git"
	"github.com/lemmi/glubcms"
	"github.com/raymondbutcher/tidyhtml"
)

func POE(err error, prefix ...interface{}) {
	if err != nil {
		log.Print(prefix...)
		log.Fatal(err)
	}
}

func parseTemplates(commit *g.Commit) (*template.Template, error) {
	ttree, err := commit.Tree.SubTree("templates")
	if err != nil {
		return nil, err
	}
	scan, err := ttree.Scanner()
	if err != nil {
		return nil, err
	}
	tmain := template.New("templatecontainer")
	for scan.Scan() {
		entry := scan.TreeEntry()
		if !strings.HasSuffix(entry.Name(), ".tmpl") {
			continue
		}
		data, err := entry.Blob().Data()
		if err != nil {
			return nil, err
		}
		defer data.Close()
		databytes, err := ioutil.ReadAll(data)
		if err != nil {
			return nil, err
		}

		_, err = tmain.New(entry.Name()).Parse(string(databytes))
		if err != nil {
			return nil, err
		}
	}

	if err := scan.Err(); err != nil {
		return nil, err
	}

	return tmain, nil
}

type StaticHandler struct {
	fs http.FileSystem
}

func (sh StaticHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ServeContentFs(w, r, sh.fs)
}
func newStaticHandler(c *g.Commit) (http.Handler, error) {
	stree, err := c.Tree.SubTree("static")
	return http.FileServer(ghfs.FromCommit(c, stree)), err
}

type pageHandler struct {
	c *g.Commit
}

func newPageHandler(c *g.Commit) http.Handler {
	return pageHandler{c}
}
func (h pageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tmpl := template.Must(parseTemplates(h.c))
	stree, err := h.c.Tree.SubTree("pages")
	POE(err, "Pages")

	p := glubcms.PageFromDir(ghfs.FromCommit(h.c, stree), r.URL.Path)
	buf := bytes.Buffer{}
	if err := tmpl.ExecuteTemplate(&buf, "main.tmpl", p); err != nil {
		log.Println(err)
		return
	}
	tbuf := bytes.Buffer{}
	if err := tidyhtml.Copy(&tbuf, &buf); err != nil {
		log.Println(err)
		return
	}
	w.Header().Set("Content-Type", "text/html")
	http.ServeContent(w, r, "", h.c.Author.When, bytes.NewReader(tbuf.Bytes()))
}

// func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker)
func ServeContentFs(w http.ResponseWriter, req *http.Request, fs http.FileSystem) {
	path := filepath.Clean(req.URL.Path)
	f, err := fs.Open(path)
	if err != nil {
		http.Error(w, path, http.StatusNotFound)
		return
	}
	defer f.Close()
	stat, err := f.Stat()
	if err != nil {
		http.Error(w, path, http.StatusInternalServerError)
		return
	}
	if stat.IsDir() {
		http.Error(w, path, http.StatusForbidden)
		return
	}
	http.ServeContent(w, req, stat.Name(), stat.ModTime(), f)
}

type handler struct {
	prefix string
}

func newHandler(prefix string) handler {
	return handler{
		prefix: prefix,
	}
}

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	path, err := filepath.Abs(h.prefix)
	POE(err, "Filepath")

	repo, err := g.OpenRepository(path)
	POE(err, "OpenRepository")

	commit, err := repo.GetCommitOfBranch("master")
	POE(err, "LookupBranch")

	mux := http.NewServeMux()

	staticHandler, err := newStaticHandler(commit)
	POE(err, "StaticHandler")

	mux.Handle("/static/", http.StripPrefix("/static/", staticHandler))
	mux.Handle("/robots.txt", staticHandler)
	mux.Handle("/favicon.ico", staticHandler)
	mux.Handle("/", newPageHandler(commit))
	mux.ServeHTTP(w, r)
}

func main() {
	prefix := flag.String("prefix", "../example_page", "path to the root dir")
	addr := flag.String("bind", "localhost:8080", "address or path to bind to")
	network := flag.String("net", "tcp", `"tcp", "tcp4", "tcp6", "unix" or "unixpacket"`)
	flag.Parse()
	ln, err := net.Listen(*network, *addr)
	if err != nil {
		panic(err)
	}
	defer ln.Close()
	if strings.HasPrefix(*network, "unix") {
		err = os.Chmod(*addr, 0666)
	}
	if err != nil {
		panic(err)
	}
	log.Fatal(http.Serve(ln, newHandler(*prefix)))
}
<commit_msg>gcserver: make more use of http.FileSystem<commit_after>package main

import (
	"bytes"
	"flag"
	"html/template"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/lemmi/ghfs"
	g "github.com/lemmi/git"
	"github.com/lemmi/glubcms"
	"github.com/raymondbutcher/tidyhtml"
)

const (
	tmplPath = "templates"
)

func POE(err error, prefix ...interface{}) {
	if err != nil {
		log.Print(prefix...)
		log.Fatal(err)
	}
}

func parseTemplates(fs http.FileSystem) (*template.Template, error) {
	dir, err := fs.Open(tmplPath)
	if err != nil {
		return nil, err
	}
	tmain := template.New("main")
	fis, err := dir.Readdir(-1)
	if err != nil {
		return nil, err
	}
	for _, fi := range fis {
		if !strings.HasSuffix(fi.Name(), ".tmpl") {
			continue
		}
		data, err := fs.Open(filepath.Join(tmplPath, fi.Name()))
		if err != nil {
			return nil, err
		}
		databytes, err := ioutil.ReadAll(data)
		data.Close()
		if err != nil {
			return nil, err
		}

		//tname := strings.TrimSuffix(fi.Name(), ".tmpl")
		_, err = tmain.New(fi.Name()).Parse(string(databytes))
		if err != nil {
			return nil, err
		}
	}

	return tmain, nil
}

type StaticHandler struct {
	fs http.FileSystem
}

func (sh StaticHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ServeContentFs(w, r, sh.fs)
}
func newStaticHandler(c *g.Commit) (http.Handler, error) {
	stree, err := c.Tree.SubTree("static")
	return http.FileServer(ghfs.FromCommit(c, stree)), err
}

type pageHandler struct {
	c *g.Commit
}

func newPageHandler(c *g.Commit) http.Handler {
	return pageHandler{c}
}
func (h pageHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tmpl := template.Must(parseTemplates(ghfs.FromCommit(h.c)))
	stree, err := h.c.Tree.SubTree("pages")
	POE(err, "Pages")

	p := glubcms.PageFromDir(ghfs.FromCommit(h.c, stree), r.URL.Path)
	buf := bytes.Buffer{}
	if err := tmpl.ExecuteTemplate(&buf, "main.tmpl", p); err != nil {
		log.Println(err)
		return
	}
	tbuf := bytes.Buffer{}
	if err := tidyhtml.Copy(&tbuf, &buf); err != nil {
		log.Println(err)
		return
	}
	w.Header().Set("Content-Type", "text/html")
	http.ServeContent(w, r, "", h.c.Author.When, bytes.NewReader(tbuf.Bytes()))
}

// func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker)
func ServeContentFs(w http.ResponseWriter, req *http.Request, fs http.FileSystem) {
	path := filepath.Clean(req.URL.Path)
	f, err := fs.Open(path)
	if err != nil {
		http.Error(w, path, http.StatusNotFound)
		return
	}
	defer f.Close()
	stat, err := f.Stat()
	if err != nil {
		http.Error(w, path, http.StatusInternalServerError)
		return
	}
	if stat.IsDir() {
		http.Error(w, path, http.StatusForbidden)
		return
	}
	http.ServeContent(w, req, stat.Name(), stat.ModTime(), f)
}

type handler struct {
	prefix string
}

func newHandler(prefix string) handler {
	return handler{
		prefix: prefix,
	}
}

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	path, err := filepath.Abs(h.prefix)
	POE(err, "Filepath")

	repo, err := g.OpenRepository(path)
	POE(err, "OpenRepository")

	commit, err := repo.GetCommitOfBranch("master")
	POE(err, "LookupBranch")

	mux := http.NewServeMux()

	staticHandler, err := newStaticHandler(commit)
	POE(err, "StaticHandler")

	mux.Handle("/static/", http.StripPrefix("/static/", staticHandler))
	mux.Handle("/robots.txt", staticHandler)
	mux.Handle("/favicon.ico", staticHandler)
	mux.Handle("/", newPageHandler(commit))
	mux.ServeHTTP(w, r)
}

func main() {
	prefix := flag.String("prefix", "../example_page", "path to the root dir")
	addr := flag.String("bind", "localhost:8080", "address or path to bind to")
	network := flag.String("net", "tcp", `"tcp", "tcp4", "tcp6", "unix" or "unixpacket"`)
	flag.Parse()
	ln, err := net.Listen(*network, *addr)
	if err != nil {
		panic(err)
	}
	defer ln.Close()
	if strings.HasPrefix(*network, "unix") {
		err = os.Chmod(*addr, 0666)
	}
	if err != nil {
		panic(err)
	}
	log.Fatal(http.Serve(ln, newHandler(*prefix)))
}
<|endoftext|>


<commit_before>package dmx

import (
	"encoding/hex"
)

type Address int
type Channel uint8

const UniverseChannels Address = 512

type Universe []Channel

func MakeUniverse() Universe {
	var universe Universe

	universe.init()

	return universe
}

func (universe *Universe) init() {
	*universe = make([]Channel, 0, UniverseChannels)
}

func (universe Universe) Bytes() []byte {
	var buf = make([]byte, len(universe))
	for i, channel := range universe {
		buf[i] = byte(channel)
	}
	return buf
}

func (universe Universe) String() string {
	return hex.Dump(universe.Bytes())
}

func (universe *Universe) Get(address Address) Channel {
	if address <= 0 || address > UniverseChannels {
		panic("Invalid DMX address")
	} else if int(address) > len(*universe) {
		return 0
	}

	return (*universe)[address-1]
}

func (universe *Universe) Set(address Address, value Channel) {
	if address <= 0 || address > UniverseChannels {
		panic("Invalid DMX address")
	} else if int(address) > len(*universe) {
		*universe = (*universe)[0:address]
	}

	(*universe)[address-1] = value
}

type Writer interface {
	WriteDMX(dmx Universe) error
}
<commit_msg>dmx: Universe.Copy()<commit_after>package dmx

import (
	"encoding/hex"
)

type Address int
type Channel uint8

const UniverseChannels Address = 512

type Universe []Channel

func MakeUniverse() Universe {
	var universe Universe

	universe.init()

	return universe
}

func (universe *Universe) init() {
	*universe = make([]Channel, 0, UniverseChannels)
}

func (universe Universe) Bytes() []byte {
	var buf = make([]byte, len(universe))
	for i, channel := range universe {
		buf[i] = byte(channel)
	}
	return buf
}

func (universe Universe) String() string {
	return hex.Dump(universe.Bytes())
}

func (universe Universe) Copy() Universe {
	var out = make(Universe, len(universe))

	copy(out, universe)

	return out
}

func (universe Universe) Get(address Address) Channel {
	if address <= 0 || address > UniverseChannels {
		panic("Invalid DMX address")
	} else if int(address) > len(universe) {
		return 0
	}

	return universe[address-1]
}

func (universe *Universe) Set(address Address, value Channel) {
	if address <= 0 || address > UniverseChannels {
		panic("Invalid DMX address")
	} else if int(address) > len(*universe) {
		*universe = (*universe)[0:address]
	}

	(*universe)[address-1] = value
}

type Writer interface {
	WriteDMX(dmx Universe) error
}
<|endoftext|>


<commit_before>package signals
/*
Package signals generates and manipulates signals:- https://en.wikipedia.org/wiki/Signal_processing.

signals are entirely procedural.

signals "any quantity exhibiting variation in time or variation in space".

currently this package supports only 1-Dimensionsal variation, and for simplicity terminolology used represents analogue variation in time.

this package is intended to be general, and so a base package for import, and used then with specific real-world quantities.

Interfaces

Signal :- method Level() returns a Level value from an Interval value parameter.
Tone :- a Signal with an additional method  Period(), that returns the signals repeat period Interval.

Main Types

Level :- a value from -MaxLevel to +MaxLevel
Interval :- a value with UnitTime somewhere near the center of its range.

*/

<commit_msg>improv<commit_after>/*
Package signals generates and manipulates signals:- https://en.wikipedia.org/wiki/Signal_processing.

signals are entirely procedural.

signals "any quantity exhibiting variation in time or variation in space".

currently this package supports only 1-Dimensionsal variation, and for simplicity terminolology used represents analogue variation in time.

this package is intended to be general, and so a base package for import, and used then with specific real-world quantities.

Interfaces

Signal :- method Level() returns a Level value from an Interval value parameter.
Tone :- a Signal with an additional method  Period(), that returns the signals repeat period Interval.

Main Types

Level :- a value from -MaxLevel to +MaxLevel
Interval :- a value with UnitTime somewhere near the center of its range.

*/
package signals

<|endoftext|>


<commit_before>/*
Package stick is a go-language port of the Twig templating engine.

Twig is a powerful templating language that promotes separation of logic
from the view.

Stick executes Twig templates using an instance of Env. An Env contains all
the configured Functions, Filters, and Tests as well as a Loader to load
named templates from any source.

Obligatory "Hello, World!" example:

	env := stick.NewEnv(nil); // A nil loader means stick will simply execute
	                          // the string passed into env.Execute.

	// Templates receive a map of string to any value.
	p := map[string]stick.Value{"name": "World"}

	// Substitute os.Stdout with any io.Writer.
	env.Execute("Hello, {{ name }}!", os.Stdout, p)

Another example, using a FilesystemLoader and responding to an HTTP request:

	import "net/http"

	// ...

	fsRoot := os.Getwd() // Templates are loaded relative to this directory.
	env := stick.NewEnv(stick.NewFilesystemLoader(fsRoot))
	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
		env.Execute("bar.html.twig", w, nil) // Loads "bar.html.twig" relative to fsRoot.
	})
	http.ListenAndServe(":80", nil)

Types and values

Any user value in Stick is represented by a stick.Value. There are three main types
in Stick when it comes to built-in operations: strings, numbers, and booleans. Of note,
numbers are represented by float64 as this matches regular Twig behavior most closely.

Stick makes no restriction on what is stored in a stick.Value, but some built-in
operators will try to coerce a value into a boolean, string, or number depending
on the operation.

Additionally, custom types that implement specific interfaces can be coerced. Stick
defines three interfaces: Stringer, Number, and Boolean. Each interface defines a single
method that should convert a custom type into the specified type.

	type myType struct {
		// ...
	}

	func (t *myType) String() string {
		return fmt.Sprintf("%v", t.someField)
	}

	func (t *myType) Number() float64 {
		return t.someFloatField
	}

	func (t *myType) Boolean() bool {
		return t.someValue != nil
	}

On a final note, there exists three functions to coerce any type into a string,
number, or boolean, respectively.

	// Coerce any value to a string
	v := stick.CoerceString(anything)

	// Coerce any value to a float64
	f := stick.CoerceNumber(anything)

	// Coerce any vale to a boolean
	b := stick.CoerceBool(anything)

User defined helpers

It is possible to define custom Filters, Functions, and boolean Tests available to
your Stick templates. Each user-defined type is simply a function with a specific
signature.

A Func represents a user-defined function.

	type Func func(e *Env, args ...Value) Value

Functions can be called anywhere expressions are allowed. Functions may take any number
of arguments.

	{% if form_valid(form) %}

A Filter is a user-defined filter.

	type Filter func(e *Env, val Value, args ...Value) Value

Filters receive a value and modify it in some way. Example of using a filter:

	{{ post|raw }}

Filters also accept zero or more arguments beyond the value to be filtered:

	{{ balance|number_format(2) }}

A Test represents a user-defined boolean test.

	type Test func(e *Env, val Value, args ...Value) bool

Tests are used to make some comparisons more expressive, for example:

	{% if users is empty %}

Tests also accept zero to any number of arguments, and Test names can contain
up to one space. Here, "divisible by" is an example of a two-word test that takes
a parameter:

	{% if loop.index is divisible by(3) %}

User-defined types are added to an Env after it is created. For example:

	env := stick.NewEnv(nil)
	env.Functions["form_valid"] = func(e *stick.Env, args ...stick.Value) stick.Value {
		// Do something useful..
		return true
	}
	env.Filters["number_format"] = func(e *stick.Env, val stick.Value, args ...stick.Value) stick.Value {
		v := stick.CoerceNumber(val)
		// Do some formatting.
		return fmt.Sprintf("%.2d", v)
	}
	env.Tests["empty"] = func(e *stick.Env, val stick.Value, args ...stick.Value) bool {
		// Probably not that useful.
		return stick.CoerceBool(val) == false
	}

For additional information on Twig, check http://twig.sensiolabs.org/
*/
package stick
<commit_msg>Tweaked doc formatting.<commit_after>/*
Package stick is a go-language port of the Twig templating engine.

Twig is a powerful templating language that promotes separation of logic
from the view.

Stick executes Twig templates using an instance of Env. An Env contains all
the configured Functions, Filters, and Tests as well as a Loader to load
named templates from any source.

Obligatory "Hello, World!" example:

	env := stick.NewEnv(nil); // A nil loader means stick will simply execute
	                          // the string passed into env.Execute.

	// Templates receive a map of string to any value.
	p := map[string]stick.Value{"name": "World"}

	// Substitute os.Stdout with any io.Writer.
	env.Execute("Hello, {{ name }}!", os.Stdout, p)

Another example, using a FilesystemLoader and responding to an HTTP request:

	import "net/http"

	// ...

	fsRoot := os.Getwd() // Templates are loaded relative to this directory.
	env := stick.NewEnv(stick.NewFilesystemLoader(fsRoot))
	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
		env.Execute("bar.html.twig", w, nil) // Loads "bar.html.twig" relative to fsRoot.
	})
	http.ListenAndServe(":80", nil)

Types and values

Any user value in Stick is represented by a stick.Value. There are three main types
in Stick when it comes to built-in operations: strings, numbers, and booleans. Of note,
numbers are represented by float64 as this matches regular Twig behavior most closely.

Stick makes no restriction on what is stored in a stick.Value, but some built-in
operators will try to coerce a value into a boolean, string, or number depending
on the operation.

Additionally, custom types that implement specific interfaces can be coerced. Stick
defines three interfaces: Stringer, Number, and Boolean. Each interface defines a single
method that should convert a custom type into the specified type.

	type myType struct {
		// ...
	}

	func (t *myType) String() string {
		return fmt.Sprintf("%v", t.someField)
	}

	func (t *myType) Number() float64 {
		return t.someFloatField
	}

	func (t *myType) Boolean() bool {
		return t.someValue != nil
	}

On a final note, there exists three functions to coerce any type into a string,
number, or boolean, respectively.

	// Coerce any value to a string
	v := stick.CoerceString(anything)

	// Coerce any value to a float64
	f := stick.CoerceNumber(anything)

	// Coerce any vale to a boolean
	b := stick.CoerceBool(anything)

User defined helpers

It is possible to define custom Filters, Functions, and boolean Tests available to
your Stick templates. Each user-defined type is simply a function with a specific
signature.

A Func represents a user-defined function.

	type Func func(e *Env, args ...Value) Value

Functions can be called anywhere expressions are allowed. Functions may take any number
of arguments.

A Filter is a user-defined filter.

	type Filter func(e *Env, val Value, args ...Value) Value

Filters receive a value and modify it in some way. Filters also accept zero or more arguments
beyond the value to be filtered.

A Test represents a user-defined boolean test.

	type Test func(e *Env, val Value, args ...Value) bool

Tests are used to make some comparisons more expressive. Tests also accept zero to any
number of arguments, and Test names can contain up to one space.

User-defined types are added to an Env after it is created. For example:

	env := stick.NewEnv(nil)
	env.Functions["form_valid"] = func(e *stick.Env, args ...stick.Value) stick.Value {
		// Do something useful..
		return true
	}
	env.Filters["number_format"] = func(e *stick.Env, val stick.Value, args ...stick.Value) stick.Value {
		v := stick.CoerceNumber(val)
		// Do some formatting.
		return fmt.Sprintf("%.2d", v)
	}
	env.Tests["empty"] = func(e *stick.Env, val stick.Value, args ...stick.Value) bool {
		// Probably not that useful.
		return stick.CoerceBool(val) == false
	}

For additional information on Twig, check http://twig.sensiolabs.org/
*/
package stick
<|endoftext|>


<commit_before>/*
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*
Cuckoo filter is a Bloom filter replacement for approximated set-membership queries.

While Bloom filters are well-known space-efficient data structures to serve queries like "if item x is in a set?", they do not support deletion. Their variances to enable deletion (like counting Bloom filters) usually require much more space.

Cuckoo filters provide the ﬂexibility to add and remove items dynamically. A cuckoo filter is based on cuckoo hashing (and therefore named as cuckoo filter). It is essentially a cuckoo hash table storing each key's fingerprint. Cuckoo hash tables can be highly compact, thus a cuckoo filter could use less space than conventional Bloom ﬁlters, for applications that require low false positive rates (< 3%).

For details about the algorithm and citations please use this article:
"Cuckoo Filter: Better Than Bloom" by Bin Fan, Dave Andersen and Michael Kaminsky
(https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf)

Note:This implementation uses a a static bucket size of 4 fingerprints and a fingerprint size of 1 byte based on my understanding of an optimal bucket/fingerprint/size ratio from the aforementioned paper.*/
package cuckoofilter
<commit_msg>Fix doc.go<commit_after>/*
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

/*
Cuckoo filter is a Bloom filter replacement for approximated set-membership queries.

While Bloom filters are well-known space-efficient data structures to serve queries like "if item x is in a set?", they do not support deletion. Their variances to enable deletion (like counting Bloom filters) usually require much more space.

Cuckoo filters provide the ﬂexibility to add and remove items dynamically. A cuckoo filter is based on cuckoo hashing (and therefore named as cuckoo filter). It is essentially a cuckoo hash table storing each key's fingerprint. Cuckoo hash tables can be highly compact, thus a cuckoo filter could use less space than conventional Bloom ﬁlters, for applications that require low false positive rates (< 3%).

For details about the algorithm and citations please use this article:

"Cuckoo Filter: Better Than Bloom" by Bin Fan, Dave Andersen and Michael Kaminsky
(https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf)

Note:
This implementation uses a a static bucket size of 4 fingerprints and a fingerprint size of 1 byte based on my understanding of an optimal bucket/fingerprint/size ratio from the aforementioned paper.*/
package cuckoofilter
<|endoftext|>


<commit_before>/*
Package byline implements Reader interface for processing io.Reader line-by-line.
You can add UNIX text processing principles to its Reader (like with awk, grep, sed ...).

Install

 go get -u github.com/msoap/byline

Usage

 import "github.com/msoap/byline"

 // Create new line-by-line Reader from io.Reader:
 lr := byline.NewReader(reader)

 // Add to the Reader stack of a filter functions:
 lr.MapString(func(line string) string {return "prefix_" + line}).GrepByRegexp(regexp.MustCompile("only this"))

 // Read all content
 result, err := lr.ReadAll()

 // Use everywhere instead of io.Reader
 _, err := io.Copy(os.Stdout, lr)

 // Or in one place
 result, err := byline.NewReader(reader).MapString(func(line string) string {return "prefix_" + line}).ReadAll()

*/
package byline
<commit_msg>gofmt with Go 1.19<commit_after>/*
Package byline implements Reader interface for processing io.Reader line-by-line.
You can add UNIX text processing principles to its Reader (like with awk, grep, sed ...).

Install

	go get -u github.com/msoap/byline

Usage

	import "github.com/msoap/byline"

	// Create new line-by-line Reader from io.Reader:
	lr := byline.NewReader(reader)

	// Add to the Reader stack of a filter functions:
	lr.MapString(func(line string) string {return "prefix_" + line}).GrepByRegexp(regexp.MustCompile("only this"))

	// Read all content
	result, err := lr.ReadAll()

	// Use everywhere instead of io.Reader
	_, err := io.Copy(os.Stdout, lr)

	// Or in one place
	result, err := byline.NewReader(reader).MapString(func(line string) string {return "prefix_" + line}).ReadAll()
*/
package byline
<|endoftext|>


<commit_before>/*
Command pigeon generates Go parsers from a PEG grammar.

From Wikipedia [0]:

	A parsing expression grammar is a type of analytic formal grammar, i.e.
	it describes a formal language in terms of a set of rules for recognizing
	strings in the language.

Its features and syntax are inspired by the PEG.js project [1], while
the implementation is loosely based on [2].

	[0]: http://en.wikipedia.org/wiki/Parsing_expression_grammar
	[1]: http://pegjs.org/
	[2]: http://www.codeproject.com/Articles/29713/Parsing-Expression-Grammar-Support-for-C-Part

Command-line usage

The pigeon tool must be called with a PEG grammar file as defined
by the accepted PEG syntax below. The grammar may be provided by a
file or read from stdin. The generated parser is written to stdout
by default.

	pigeon [options] [GRAMMAR_FILE]

The following options can be specified:

	-debug : boolean, print debugging info to stdout (default: false).

	-o=FILE : string, output file where the generated parser will be
	written (default: stdout).

	-x : boolean, if set, do not build the parser, just parse the input grammar
	(default: false).

	-receiver-name=NAME : string, name of the receiver variable for the generated
	code blocks. Non-initializer code blocks in the grammar end up as methods on the
	*current type, and this option sets the name of the receiver (default: c).

The tool makes no attempt to format the code, nor to detect the
required imports. It is recommended to use goimports to properly generate
the output code:
	pigeon GRAMMAR_FILE | goimports > output_file.go

The goimports tool can be installed with:
	go get golang.org/x/tools/cmd/goimports

If the code blocks in the grammar are golint- and go vet-compliant, then
the resulting generated code will also be golint- and go vet-compliant.

The generated code doesn't use any third-party dependency unless code blocks
in the grammar require such a dependency.

PEG syntax

The accepted syntax for the grammar is formally defined in the
grammar/pigeon.peg file, using the PEG syntax. What follows is an informal
description of this syntax.

Error reporting

*/
package main
<commit_msg>doc: document all types of expressions<commit_after>/*
Command pigeon generates Go parsers from a PEG grammar.

From Wikipedia [0]:

	A parsing expression grammar is a type of analytic formal grammar, i.e.
	it describes a formal language in terms of a set of rules for recognizing
	strings in the language.

Its features and syntax are inspired by the PEG.js project [1], while
the implementation is loosely based on [2].

	[0]: http://en.wikipedia.org/wiki/Parsing_expression_grammar
	[1]: http://pegjs.org/
	[2]: http://www.codeproject.com/Articles/29713/Parsing-Expression-Grammar-Support-for-C-Part

Command-line usage

The pigeon tool must be called with a PEG grammar file as defined
by the accepted PEG syntax below. The grammar may be provided by a
file or read from stdin. The generated parser is written to stdout
by default.

	pigeon [options] [GRAMMAR_FILE]

The following options can be specified:

	-debug : boolean, print debugging info to stdout (default: false).

	-o=FILE : string, output file where the generated parser will be
	written (default: stdout).

	-x : boolean, if set, do not build the parser, just parse the input grammar
	(default: false).

	-receiver-name=NAME : string, name of the receiver variable for the generated
	code blocks. Non-initializer code blocks in the grammar end up as methods on the
	*current type, and this option sets the name of the receiver (default: c).

The tool makes no attempt to format the code, nor to detect the
required imports. It is recommended to use goimports to properly generate
the output code:
	pigeon GRAMMAR_FILE | goimports > output_file.go

The goimports tool can be installed with:
	go get golang.org/x/tools/cmd/goimports

If the code blocks in the grammar are golint- and go vet-compliant, then
the resulting generated code will also be golint- and go vet-compliant.

The generated code doesn't use any third-party dependency unless code blocks
in the grammar require such a dependency.

PEG syntax

The accepted syntax for the grammar is formally defined in the
grammar/pigeon.peg file, using the PEG syntax. What follows is an informal
description of this syntax.

Identifiers, whitespace, comments and literals follow the same
notation as the Go language, as defined in the language specification
(http://golang.org/ref/spec#Source_code_representation):

	// single line comment*/
//	/* multi-line comment */
/*	'x' (single quotes for single char literal)
	"double quotes for string literal"
	`backtick quotes for raw string literal`
	RuleName (a valid identifier)

The grammar must be Unicode text encoded in UTF-8. New lines are identified
by the \n character (U+000A). Space (U+0020), horizontal tabs (U+0009) and
carriage returns (U+000D) are considered whitespace and are ignored except
to separate tokens.

Rules

A PEG grammar is composed of a list of rules. A rule is an identifier followed
by a rule definition operator and an expression. An optional display name -
a string literal used in error messages instead of the rule identifier - can
be specified after the rule identifier. E.g.:
	RuleA = 'a'+ // RuleA is one or more lowercase 'a's

The rule definition operator can be any one of those:
	=, <-, ← (U+2190), ⟵ (U+27F5)

Expressions

A rule is defined by an expression. The following sections describe the
various expression types. Expressions can be grouped by using parentheses,
and a rule can be referenced by its identifier in place of an expression.

Choice expression

The choice expression is a list of expressions that will be tested in the
order they are defined. The first one that matches will be used. Expressions
are separated by the forward slash character "/". E.g.:
	ChoiceExpr = A / B / C // A, B and C should be rules declared in the grammar

Because the first match is used, it is important to think about the order
of expressions. For example, in this rule, "<=" would never be used because
the "<" expression comes first:
	BadChoiceExpr = "<" / "<="

Sequence expression

The sequence expression is a list of expressions that must all match in
that same order for the sequence expression to be considered a match.
Expressions are separated by whitespace. E.g.:
	SeqExpr = "A" "b" "c" // matches "Abc", but not "Acb"

Labeled expression

A labeled expression consists of an identifier followed by a colon ":"
and an expression. A labeled expression introduces a variable named with
the label that can be referenced in the parent expression's code block.
The variable will have the value of the expression that follows the colon.
E.g.:
	LabeledExpr = value:[a-z]+ {
		fmt.Println(value)
		return value, nil
	}

And (&) and not (!) expression

An expression prefixed with the ampersand "&" is the "and" predicate
expression: it is considered a match if the following expression is a match,
but it does not consume any input.

An expression prefixed with the exclamation point "!" is a predicate
expression: it is considered a match if the following expression is not
a match, but it does not consume any input. E.g.:
	AndExpr = "A" &"B" // matches "A" if followed by a "B" (does not consume "B")
	NotExpr = "A" !"B" // matches "A" if not followed by a "B" (does not consume "B")

The expression following the & and ! operators can be a code block. In that
case, the code block must return a bool and an error. The operator's semantic
is the same, & is a match if the code block returns true, ! is a match if the
code block returns false. The code block has access to any labeled value
defined in its scope. E.g.:
	CodeAndExpr = value:[a-z] &{
		// can access the value local variable...
		return true, nil
	}

Repeating expressions

An expression followed by "*", "?" or "+" is a match if the expression
occurs zero or more times ("*"), zero or one time "?" or one or more times
("+") respectively. The match is greedy, it will match as many times as
possible. E.g.
	ZeroOrMoreAs = "A"*

Literal matcher

Character class matcher

Any matcher

Code block

Using the generated parser

TODO: Start rule is the first rule. Example package to document the exported symbols.

Error reporting

TODO: List of errors, ParserError type, grammar example to handle common error (like
non-terminated string literal), panic.

*/
package main
<|endoftext|>


<commit_before>/*

Watchdog is an in-process task scheduler and simple execution monitor.
Watchdog accepts a workload and runs it at the specified interval.

Here is a simple but functioning example:

	import (
		"fmt"
		"github.com/deafbybeheading/watchdog"
		"time"
	)

	func main() {
		w := watchdog.Watch(&Task{
			Schedule: 1 * time.Second,
			Command: func(t time.Time) error {
				return fmt.Printf("the time is %v\n", t)
			},
			Timeout: 10 * time.Milliseconds,
		})
		loop: for {
			executions := 0
			stalls := 0
			select {
			case exec := <- w.Executions():
				executions += 1
				fmt.Printf("invoked at %v; ran %v times\n",
					exec.StartedAt, executions)
				if err := exec.Error; err != nil {
					fmt.Printf("encountered error: %v\n", err)
				}
			case stall := <- w.Stalls():
				fmt.Printf("execution %v stalled at %v\n",
					executions + 1, stall.StalledAt)
			case <- time.After(10 * time.Second):
				fmt.Println("done!")
				break loop
			}
		}
	}

*/
<commit_msg>Expand on package docs<commit_after>/*

Watchdog is an in-process task scheduler and simple execution monitor.
Watchdog accepts a workload and runs it at the specified interval.

Watchdog exposes two channels for monitoring its workload: Executions
and Stalls. Executions are sent for every invocation of a workload
Task, and stalls are only sent if a Task invocation takes longer than
a specified timeout.

A Watchdog is created with the Watch method, and starts running its
workload immediately. Its execution semantics are very close to those
of time.Ticker: a single tick may be "queued up" at any time if the
command takes longer to execute than the scheduling period.

A Watchdog may be stopped with the Stop command. If a task is
currently executing, that task will complete before Stop returns, and
information about its execution and stall (if any) will be sent on the
standard channels.

Here is a simple but functioning example:

	import (
		"fmt"
		"github.com/deafbybeheading/watchdog"
		"time"
	)

	func main() {
		w := watchdog.Watch(&Task{
			Schedule: 1 * time.Second,
			Command: func(t time.Time) error {
				return fmt.Printf("the time is %v\n", t)
			},
			Timeout: 10 * time.Milliseconds,
		})
		loop: for {
			executions := 0
			stalls := 0
			select {
			case exec := <- w.Executions():
				executions += 1
				fmt.Printf("invoked at %v; ran %v times\n",
					exec.StartedAt, executions)
				if err := exec.Error; err != nil {
					fmt.Printf("encountered error: %v\n", err)
				}
			case stall := <- w.Stalls():
				fmt.Printf("execution %v stalled at %v\n",
					executions + 1, stall.StalledAt)
			case <- time.After(10 * time.Second):
				fmt.Println("done!")
				break loop
			}
		}
	}

*/
<|endoftext|>


<commit_before>/*
Package badger implements an embeddable, simple and fast key-value store,
written in pure Go. It is designed to be highly performant for both reads and
writes simultaneously. Badger uses Multi-Version Concurrency Control (MVCC), and
supports transactions. It runs transactions concurrently, with serializable
snapshot isolation guarantees.

Badger uses an LSM tree along with a value log to separate keys from values,
hence reducing both write amplification and the size of the LSM tree. This
allows LSM tree to be served entirely from RAM, while the values are served
from SSD.

Usage

Badger has the following main types: DB, Txn, Item and Iterator. DB contains
keys that are associated with values. It must be opened with the appropriate
options before it can be accessed.

All operations happen inside a Txn. Txn represents a transaction, which can
be read-only or read-write. Read-only transactions can read values for a
given key (which are returned inside an Item), or iterate over a set of
key-value pairs using an Iterator (which are returned as Item type values as
well). Read-write transactions can also update and delete keys from the DB.

See the examples for more usage details.
*/
package badger
<commit_msg>s/store/database<commit_after>/*
Package badger implements an embeddable, simple and fast key-value database,
written in pure Go. It is designed to be highly performant for both reads and
writes simultaneously. Badger uses Multi-Version Concurrency Control (MVCC), and
supports transactions. It runs transactions concurrently, with serializable
snapshot isolation guarantees.

Badger uses an LSM tree along with a value log to separate keys from values,
hence reducing both write amplification and the size of the LSM tree. This
allows LSM tree to be served entirely from RAM, while the values are served
from SSD.

Usage

Badger has the following main types: DB, Txn, Item and Iterator. DB contains
keys that are associated with values. It must be opened with the appropriate
options before it can be accessed.

All operations happen inside a Txn. Txn represents a transaction, which can
be read-only or read-write. Read-only transactions can read values for a
given key (which are returned inside an Item), or iterate over a set of
key-value pairs using an Iterator (which are returned as Item type values as
well). Read-write transactions can also update and delete keys from the DB.

See the examples for more usage details.
*/
package badger
<|endoftext|>


<commit_before>package github

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"

	"github.com/github/hub/Godeps/_workspace/src/github.com/howeyc/gopass"
	"github.com/github/hub/utils"
)

var (
	defaultConfigsFile = filepath.Join(os.Getenv("HOME"), ".config", "hub")
)

type yamlHost struct {
	User       string `yaml:"user"`
	OAuthToken string `yaml:"oauth_token"`
	Protocol   string `yaml:"protocol"`
}

type yamlConfig map[string][]yamlHost

type Host struct {
	Host        string `toml:"host"`
	User        string `toml:"user"`
	AccessToken string `toml:"access_token"`
	Protocol    string `toml:"protocol"`
}

type Config struct {
	Hosts []Host `toml:"hosts"`
}

func (c *Config) PromptForHost(host string) (h *Host, err error) {
	h = c.Find(host)
	if h != nil {
		return
	}

	user := c.PromptForUser()
	pass := c.PromptForPassword(host, user)

	client := NewClient(host)
	var code, token string
	for {
		token, err = client.FindOrCreateToken(user, pass, code)
		if err == nil {
			break
		}

		if ae, ok := err.(*AuthError); ok && ae.IsRequired2FACodeError() {
			if (code != "") {
				fmt.Fprintln(os.Stderr, "warning: invalid two-factor code")
			}
			code = c.PromptForOTP()
		} else {
			break
		}
	}

	if err != nil {
		return
	}

	client.Host.AccessToken = token
	currentUser, err := client.CurrentUser()
	if err != nil {
		return
	}

	h = &Host{
		Host:        host,
		User:        currentUser.Login,
		AccessToken: token,
		Protocol:    "https",
	}
	c.Hosts = append(c.Hosts, *h)
	err = newConfigService().Save(configsFile(), c)

	return
}

func (c *Config) PromptForUser() (user string) {
	user = os.Getenv("GITHUB_USER")
	if user != "" {
		return
	}

	fmt.Printf("%s username: ", GitHubHost)
	user = c.scanLine()

	return
}

func (c *Config) PromptForPassword(host, user string) (pass string) {
	pass = os.Getenv("GITHUB_PASSWORD")
	if pass != "" {
		return
	}

	fmt.Printf("%s password for %s (never stored): ", host, user)
	if isTerminal(os.Stdout.Fd()) {
		pass = string(gopass.GetPasswd())
	} else {
		pass = c.scanLine()
	}

	return
}

func (c *Config) PromptForOTP() string {
	fmt.Print("two-factor authentication code: ")
	return c.scanLine()
}

func (c *Config) scanLine() string {
	var line string
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		line = scanner.Text()
	}
	utils.Check(scanner.Err())

	return line
}

func (c *Config) Find(host string) *Host {
	for _, h := range c.Hosts {
		if h.Host == host {
			return &h
		}
	}

	return nil
}

func (c *Config) selectHost() *Host {
	options := len(c.Hosts)

	if options == 1 {
		return &c.Hosts[0]
	}

	prompt := "Select host:\n"
	for idx, host := range c.Hosts {
		prompt += fmt.Sprintf(" %d. %s\n", idx+1, host.Host)
	}
	prompt += fmt.Sprint("> ")

	fmt.Printf(prompt)
	index := c.scanLine()
	i, err := strconv.Atoi(index)
	if err != nil || i < 1 || i > options {
		utils.Check(fmt.Errorf("Error: must enter a number [1-%d]", options))
	}

	return &c.Hosts[i-1]
}

func configsFile() string {
	configsFile := os.Getenv("GH_CONFIG")
	if configsFile == "" {
		configsFile = defaultConfigsFile
	}

	return configsFile
}

func CurrentConfig() *Config {
	c := &Config{}
	newConfigService().Load(configsFile(), c)

	return c
}

func (c *Config) DefaultHost() (host *Host, err error) {
	if GitHubHostEnv != "" {
		host, err = c.PromptForHost(GitHubHostEnv)
	} else if len(c.Hosts) > 0 {
		host = c.selectHost()
	} else {
		host, err = c.PromptForHost(DefaultGitHubHost())
	}

	return
}

// Public for testing purpose
func CreateTestConfigs(user, token string) *Config {
	f, _ := ioutil.TempFile("", "test-config")
	defaultConfigsFile = f.Name()

	host := Host{
		User:        "jingweno",
		AccessToken: "123",
		Host:        GitHubHost,
	}

	c := &Config{Hosts: []Host{host}}
	err := newConfigService().Save(f.Name(), c)
	if err != nil {
		panic(err)
	}

	return c
}
<commit_msg>Fix prompt for user host for GHE<commit_after>package github

import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"

	"github.com/github/hub/Godeps/_workspace/src/github.com/howeyc/gopass"
	"github.com/github/hub/utils"
)

var (
	defaultConfigsFile = filepath.Join(os.Getenv("HOME"), ".config", "hub")
)

type yamlHost struct {
	User       string `yaml:"user"`
	OAuthToken string `yaml:"oauth_token"`
	Protocol   string `yaml:"protocol"`
}

type yamlConfig map[string][]yamlHost

type Host struct {
	Host        string `toml:"host"`
	User        string `toml:"user"`
	AccessToken string `toml:"access_token"`
	Protocol    string `toml:"protocol"`
}

type Config struct {
	Hosts []Host `toml:"hosts"`
}

func (c *Config) PromptForHost(host string) (h *Host, err error) {
	h = c.Find(host)
	if h != nil {
		return
	}

	user := c.PromptForUser(host)
	pass := c.PromptForPassword(host, user)

	client := NewClient(host)
	var code, token string
	for {
		token, err = client.FindOrCreateToken(user, pass, code)
		if err == nil {
			break
		}

		if ae, ok := err.(*AuthError); ok && ae.IsRequired2FACodeError() {
			if code != "" {
				fmt.Fprintln(os.Stderr, "warning: invalid two-factor code")
			}
			code = c.PromptForOTP()
		} else {
			break
		}
	}

	if err != nil {
		return
	}

	client.Host.AccessToken = token
	currentUser, err := client.CurrentUser()
	if err != nil {
		return
	}

	h = &Host{
		Host:        host,
		User:        currentUser.Login,
		AccessToken: token,
		Protocol:    "https",
	}
	c.Hosts = append(c.Hosts, *h)
	err = newConfigService().Save(configsFile(), c)

	return
}

func (c *Config) PromptForUser(host string) (user string) {
	user = os.Getenv("GITHUB_USER")
	if user != "" {
		return
	}

	fmt.Printf("%s username: ", host)
	user = c.scanLine()

	return
}

func (c *Config) PromptForPassword(host, user string) (pass string) {
	pass = os.Getenv("GITHUB_PASSWORD")
	if pass != "" {
		return
	}

	fmt.Printf("%s password for %s (never stored): ", host, user)
	if isTerminal(os.Stdout.Fd()) {
		pass = string(gopass.GetPasswd())
	} else {
		pass = c.scanLine()
	}

	return
}

func (c *Config) PromptForOTP() string {
	fmt.Print("two-factor authentication code: ")
	return c.scanLine()
}

func (c *Config) scanLine() string {
	var line string
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		line = scanner.Text()
	}
	utils.Check(scanner.Err())

	return line
}

func (c *Config) Find(host string) *Host {
	for _, h := range c.Hosts {
		if h.Host == host {
			return &h
		}
	}

	return nil
}

func (c *Config) selectHost() *Host {
	options := len(c.Hosts)

	if options == 1 {
		return &c.Hosts[0]
	}

	prompt := "Select host:\n"
	for idx, host := range c.Hosts {
		prompt += fmt.Sprintf(" %d. %s\n", idx+1, host.Host)
	}
	prompt += fmt.Sprint("> ")

	fmt.Printf(prompt)
	index := c.scanLine()
	i, err := strconv.Atoi(index)
	if err != nil || i < 1 || i > options {
		utils.Check(fmt.Errorf("Error: must enter a number [1-%d]", options))
	}

	return &c.Hosts[i-1]
}

func configsFile() string {
	configsFile := os.Getenv("GH_CONFIG")
	if configsFile == "" {
		configsFile = defaultConfigsFile
	}

	return configsFile
}

func CurrentConfig() *Config {
	c := &Config{}
	newConfigService().Load(configsFile(), c)

	return c
}

func (c *Config) DefaultHost() (host *Host, err error) {
	if GitHubHostEnv != "" {
		host, err = c.PromptForHost(GitHubHostEnv)
	} else if len(c.Hosts) > 0 {
		host = c.selectHost()
	} else {
		host, err = c.PromptForHost(DefaultGitHubHost())
	}

	return
}

// Public for testing purpose
func CreateTestConfigs(user, token string) *Config {
	f, _ := ioutil.TempFile("", "test-config")
	defaultConfigsFile = f.Name()

	host := Host{
		User:        "jingweno",
		AccessToken: "123",
		Host:        GitHubHost,
	}

	c := &Config{Hosts: []Host{host}}
	err := newConfigService().Save(f.Name(), c)
	if err != nil {
		panic(err)
	}

	return c
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"fmt"
	"testing"
)

var starting_hash string = "b1dc9af6f6d8d7ce5d5a0fff1cee73ae9d44c7bb"
var md5_of_starting_file string = "0566ec561947146909cf40192cda39ec"

func TestDisplayingObject(t *testing.T) {
	first_commit, err := get_object(starting_hash, "gitserve.go")

	first_file_calculated_md5 := fmt.Sprintf("%x", md5.Sum(first_commit))

	if err != nil {
		t.Error(err)
	}
	if first_file_calculated_md5 != md5_of_starting_file {
		t.Errorf("%s came back- not %s\n", first_file_calculated_md5, md5_of_starting_file)
	}
}

func TestDisplayingMissingObject(t *testing.T) {
	first_commit, err := get_object(starting_hash, "quack")

	if err == nil {
		t.Error("This should be an error- this is not a legit file")
	}
	if first_commit != nil {
		t.Errorf("What are you doing returning content here? '%q'", first_commit)
	}
}
<commit_msg>Add test for bad hash handling<commit_after>package main

import (
	"crypto/md5"
	"fmt"
	"testing"
)

var starting_hash string = "b1dc9af6f6d8d7ce5d5a0fff1cee73ae9d44c7bb"
var md5_of_starting_file string = "0566ec561947146909cf40192cda39ec"

func TestDisplayingObject(t *testing.T) {
	first_commit, err := get_object(starting_hash, "gitserve.go")

	first_file_calculated_md5 := fmt.Sprintf("%x", md5.Sum(first_commit))

	if err != nil {
		t.Error(err)
	}
	if first_file_calculated_md5 != md5_of_starting_file {
		t.Errorf("%s came back- not %s\n", first_file_calculated_md5, md5_of_starting_file)
	}
}

func TestDisplayingMissingObject(t *testing.T) {
	first_commit, err := get_object(starting_hash, "quack")

	if err == nil {
		t.Error("This should be an error- this is not a legit file")
	}
	if first_commit != nil {
		t.Errorf("What are you doing returning content here? '%q'", first_commit)
	}
}

func TestDisplayingBadRoot(t *testing.T) {
	first_commit, err := get_object("invalid_hash", "gitserve.go")

	if err == nil {
		t.Error("This should be an error- this is not a legit hash")
	}
	if first_commit != nil {
		t.Errorf("What are you doing returning content here? '%q'", first_commit)
	}
}
<|endoftext|>