<commit_before>package edit

import (
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/parse"
)

// A completer takes the current node
type completer func(parse.Node, *Editor) []*candidate

var completers = []struct {
	name string
	completer
}{
	{"variable", complVariable},
	{"command name", complNewForm},
	{"command name", makeCompoundCompleter(complFormHead)},
	{"argument", complNewArg},
	{"argument", makeCompoundCompleter(complArg)},
}

func complVariable(n parse.Node, ed *Editor) []*candidate {
	primary, ok := n.(*parse.Primary)
	if !ok || primary.Type != parse.Variable {
		return nil
	}

	head := primary.Value
	cands := []*candidate{}
	for variable := range ed.evaler.Global() {
		if strings.HasPrefix(variable, head) {
			cands = append(cands, &candidate{
				source: styled{variable[len(head):], styleForType[Variable]},
				menu:   styled{"$" + variable, ""}})
		}
	}
	return cands
}

func complNewForm(n parse.Node, ed *Editor) []*candidate {
	if _, ok := n.(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	if _, ok := n.Parent().(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	return nil
}

func makeCompoundCompleter(
	f func(*parse.Compound, string, *Editor) []*candidate) completer {
	return func(n parse.Node, ed *Editor) []*candidate {
		pn, ok := n.(*parse.Primary)
		if !ok {
			return nil
		}
		cn, head := simpleCompound(pn)
		if cn == nil {
			return nil
		}
		return f(cn, head, ed)
	}
}

func complFormHead(cn *parse.Compound, head string, ed *Editor) []*candidate {
	if isFormHead(cn) {
		return complFormHeadInner(head, ed)
	}
	return nil
}

func complFormHeadInner(head string, ed *Editor) []*candidate {
	if eval.DontSearch(head) {
		return complArgInner(head, ed, true)
	}

	cands := []*candidate{}

	foundCommand := func(s string) {
		if strings.HasPrefix(s, head) {
			cands = append(cands, &candidate{
				source: styled{s[len(head):], styleForGoodCommand},
				menu:   styled{s, ""},
			})
		}
	}
	for special := range isBuiltinSpecial {
		foundCommand(special)
	}
	for variable := range ed.evaler.Global() {
		if strings.HasPrefix(variable, eval.FnPrefix) {
			foundCommand(variable[len(eval.FnPrefix):])
		}
	}
	for command := range ed.isExternal {
		foundCommand(command)
	}
	return cands
}

func complNewArg(n parse.Node, ed *Editor) []*candidate {
	sn, ok := n.(*parse.Sep)
	if !ok {
		return nil
	}
	if _, ok := sn.Parent().(*parse.Form); !ok {
		return nil
	}
	return complArgInner("", ed, false)
}

func complArg(cn *parse.Compound, head string, ed *Editor) []*candidate {
	return complArgInner(head, ed, false)
}

// TODO: getStyle does redundant stats.
func complArgInner(head string, ed *Editor, formHead bool) []*candidate {
	dir, fileprefix := path.Split(head)
	if dir == "" {
		dir = "."
	}

	infos, err := ioutil.ReadDir(dir)
	cands := []*candidate{}

	if err != nil {
		ed.addTip("cannot list directory %s: %v", dir, err)
		return cands
	}

	// Make candidates out of elements that match the file component.
	for _, info := range infos {
		name := info.Name()
		// Irrevelant file.
		if !strings.HasPrefix(name, fileprefix) {
			continue
		}
		// Hide dot files unless file starts with a dot.
		if !dotfile(fileprefix) && dotfile(name) {
			continue
		}
		// Only accept searchable directories and executable files if
		// completing head.
		if formHead && !(info.IsDir() || (info.Mode()&0111) != 0) {
			continue
		}

		// Full filename for .getStyle.
		full := head + name[len(fileprefix):]

		if info.IsDir() {
			name += "/"
		} else {
			name += " "
		}

		cands = append(cands, &candidate{
			source: styled{name[len(fileprefix):], ""},
			menu:   styled{name, defaultLsColor.getStyle(full)},
		})
	}

	return cands
}

func dotfile(fname string) bool {
	return strings.HasPrefix(fname, ".")
}

func isDir(fname string) bool {
	stat, err := os.Stat(fname)
	return err == nil && stat.IsDir()
}
<commit_msg>Sort variables in completion.<commit_after>package edit

import (
	"io/ioutil"
	"os"
	"path"
	"sort"
	"strings"

	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/parse"
)

// A completer takes the current node
type completer func(parse.Node, *Editor) []*candidate

var completers = []struct {
	name string
	completer
}{
	{"variable", complVariable},
	{"command name", complNewForm},
	{"command name", makeCompoundCompleter(complFormHead)},
	{"argument", complNewArg},
	{"argument", makeCompoundCompleter(complArg)},
}

func complVariable(n parse.Node, ed *Editor) []*candidate {
	primary, ok := n.(*parse.Primary)
	if !ok || primary.Type != parse.Variable {
		return nil
	}

	head := primary.Value

	// Collect matching variables.
	var varnames []string
	for varname := range ed.evaler.Global() {
		if strings.HasPrefix(varname, head) {
			varnames = append(varnames, varname)
		}
	}
	sort.Strings(varnames)

	// Build candidates.
	cands := []*candidate{}
	for _, varname := range varnames {
		cands = append(cands, &candidate{
			source: styled{varname[len(head):], styleForType[Variable]},
			menu:   styled{"$" + varname, ""}})
	}

	return cands
}

func complNewForm(n parse.Node, ed *Editor) []*candidate {
	if _, ok := n.(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	if _, ok := n.Parent().(*parse.Chunk); ok {
		return complFormHeadInner("", ed)
	}
	return nil
}

func makeCompoundCompleter(
	f func(*parse.Compound, string, *Editor) []*candidate) completer {
	return func(n parse.Node, ed *Editor) []*candidate {
		pn, ok := n.(*parse.Primary)
		if !ok {
			return nil
		}
		cn, head := simpleCompound(pn)
		if cn == nil {
			return nil
		}
		return f(cn, head, ed)
	}
}

func complFormHead(cn *parse.Compound, head string, ed *Editor) []*candidate {
	if isFormHead(cn) {
		return complFormHeadInner(head, ed)
	}
	return nil
}

func complFormHeadInner(head string, ed *Editor) []*candidate {
	if eval.DontSearch(head) {
		return complArgInner(head, ed, true)
	}

	cands := []*candidate{}

	foundCommand := func(s string) {
		if strings.HasPrefix(s, head) {
			cands = append(cands, &candidate{
				source: styled{s[len(head):], styleForGoodCommand},
				menu:   styled{s, ""},
			})
		}
	}
	for special := range isBuiltinSpecial {
		foundCommand(special)
	}
	for variable := range ed.evaler.Global() {
		if strings.HasPrefix(variable, eval.FnPrefix) {
			foundCommand(variable[len(eval.FnPrefix):])
		}
	}
	for command := range ed.isExternal {
		foundCommand(command)
	}
	return cands
}

func complNewArg(n parse.Node, ed *Editor) []*candidate {
	sn, ok := n.(*parse.Sep)
	if !ok {
		return nil
	}
	if _, ok := sn.Parent().(*parse.Form); !ok {
		return nil
	}
	return complArgInner("", ed, false)
}

func complArg(cn *parse.Compound, head string, ed *Editor) []*candidate {
	return complArgInner(head, ed, false)
}

// TODO: getStyle does redundant stats.
func complArgInner(head string, ed *Editor, formHead bool) []*candidate {
	dir, fileprefix := path.Split(head)
	if dir == "" {
		dir = "."
	}

	infos, err := ioutil.ReadDir(dir)
	cands := []*candidate{}

	if err != nil {
		ed.addTip("cannot list directory %s: %v", dir, err)
		return cands
	}

	// Make candidates out of elements that match the file component.
	for _, info := range infos {
		name := info.Name()
		// Irrevelant file.
		if !strings.HasPrefix(name, fileprefix) {
			continue
		}
		// Hide dot files unless file starts with a dot.
		if !dotfile(fileprefix) && dotfile(name) {
			continue
		}
		// Only accept searchable directories and executable files if
		// completing head.
		if formHead && !(info.IsDir() || (info.Mode()&0111) != 0) {
			continue
		}

		// Full filename for .getStyle.
		full := head + name[len(fileprefix):]

		if info.IsDir() {
			name += "/"
		} else {
			name += " "
		}

		cands = append(cands, &candidate{
			source: styled{name[len(fileprefix):], ""},
			menu:   styled{name, defaultLsColor.getStyle(full)},
		})
	}

	return cands
}

func dotfile(fname string) bool {
	return strings.HasPrefix(fname, ".")
}

func isDir(fname string) bool {
	stat, err := os.Stat(fname)
	return err == nil && stat.IsDir()
}
<|endoftext|>


<commit_before>// Copyright 2021 The Ebiten 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 go2cpp

import (
	"io"
	"runtime"
	"sync"
	"syscall/js"
)

const (
	readChunkSize = 4096
)

type Context struct {
	v               js.Value
	sampleRate      int
	channelNum      int
	bitDepthInBytes int
}

func NewContext(sampleRate int, channelNum, bitDepthInBytes int) *Context {
	v := js.Global().Get("go2cpp").Call("createAudio", sampleRate, channelNum, bitDepthInBytes)
	return &Context{
		v:               v,
		sampleRate:      sampleRate,
		channelNum:      channelNum,
		bitDepthInBytes: bitDepthInBytes,
	}
}

func (c *Context) NewPlayer(r io.Reader) *Player {
	cond := sync.NewCond(&sync.Mutex{})
	onwritten := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		cond.Signal()
		return nil
	})
	p := &Player{
		context:   c,
		src:       r,
		volume:    1,
		cond:      cond,
		onWritten: onwritten,
	}
	runtime.SetFinalizer(p, (*Player).Close)
	return p
}

func (c *Context) Close() error {
	return nil
}

func (c *Context) oneBufferSize() int {
	// TODO: This must be audio.oneBufferSize(p.context.sampleRate). Avoid the duplication.
	return c.sampleRate * c.channelNum * c.bitDepthInBytes / 4
}

func (c *Context) MaxBufferSize() int {
	// TODO: This must be audio.maxBufferSize(p.context.sampleRate). Avoid the duplication.
	return c.oneBufferSize() * 2
}

type playerState int

const (
	playerStatePaused playerState = iota
	playerStatePlaying
	playerStateClosed
)

type Player struct {
	context *Context
	src     io.Reader
	v       js.Value
	state   playerState
	volume  float64
	cond    *sync.Cond
	err     error
	buf     []byte

	onWritten js.Func
}

func (p *Player) Pause() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return
	}
	if !p.v.Truthy() {
		return
	}

	p.v.Call("pause")
	p.state = playerStatePaused
	p.cond.Signal()
}

func (p *Player) Play() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return
	}

	var runloop bool
	if !p.v.Truthy() {
		p.v = p.context.v.Call("createPlayer", p.onWritten)
		p.v.Set("volume", p.volume)
		runloop = true
	}

	p.v.Call("play")

	// Prepare the first data as soon as possible, or the audio can get stuck.
	// TODO: Get the appropriate buffer size from the C++ side.
	if p.buf == nil {
		n := p.context.oneBufferSize()
		if max := p.context.MaxBufferSize() - int(p.UnplayedBufferSize()); n > max {
			n = max
		}
		p.buf = make([]byte, n)
	}
	n, err := p.src.Read(p.buf)
	if err != nil && err != io.EOF {
		p.setError(err)
		return
	}
	if n > 0 {
		dst := js.Global().Get("Uint8Array").New(n)
		p.writeImpl(dst, p.buf[:n])
	}

	if runloop {
		go p.loop()
	}
	p.state = playerStatePlaying
	p.cond.Signal()
}

func (p *Player) IsPlaying() bool {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	return p.state == playerStatePlaying
}

func (p *Player) Reset() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return
	}
	p.state = playerStatePaused

	if !p.v.Truthy() {
		return
	}

	p.v.Call("close", true)
	p.v = js.Undefined()
	p.cond.Signal()
}

func (p *Player) Volume() float64 {
	if !p.v.Truthy() {
		return p.volume
	}
	return p.v.Get("volume").Float()
}

func (p *Player) SetVolume(volume float64) {
	if !p.v.Truthy() {
		return
	}
	p.v.Set("volume", volume)
	p.volume = volume
}

func (p *Player) UnplayedBufferSize() int64 {
	if !p.v.Truthy() {
		return 0
	}
	return int64(p.v.Get("unplayedBufferSize").Int())
}

func (p *Player) Err() error {
	return p.err
}

func (p *Player) Close() error {
	runtime.SetFinalizer(p, nil)
	return p.close(true)
}

func (p *Player) close(remove bool) error {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return p.err
	}

	if p.v.Truthy() {
		p.v.Call("close", false)
		p.v = js.Undefined()
	}
	if remove {
		p.state = playerStateClosed
		p.onWritten.Release()
	} else {
		p.state = playerStatePaused
	}
	p.cond.Signal()
	return p.err
}

func (p *Player) setError(err error) {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state != playerStateClosed && p.v.Truthy() {
		p.v.Call("close", true)
		p.v = js.Undefined()
	}
	p.err = err
	p.state = playerStateClosed
	p.cond.Signal()
}

func (p *Player) shouldWait() bool {
	if !p.v.Truthy() {
		return false
	}
	switch p.state {
	case playerStatePaused:
		return true
	case playerStatePlaying:
		return p.v.Get("unplayedBufferSize").Int() >= p.context.MaxBufferSize()
	}
	return false
}

func (p *Player) waitUntilUnpaused() bool {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	for p.shouldWait() {
		p.cond.Wait()
	}
	return p.v.Truthy() && p.state == playerStatePlaying
}

func (p *Player) write(dst js.Value, src []byte) {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()
	p.writeImpl(dst, src)
}

func (p *Player) writeImpl(dst js.Value, src []byte) {
	if p.state == playerStateClosed {
		return
	}
	if !p.v.Truthy() {
		return
	}

	js.CopyBytesToJS(dst, src)
	p.v.Call("write", dst, len(src))
}

func (p *Player) loop() {
	buf := make([]byte, readChunkSize)
	dst := js.Global().Get("Uint8Array").New(readChunkSize)

	for {
		if !p.waitUntilUnpaused() {
			return
		}

		n := readChunkSize
		if max := p.context.MaxBufferSize() - int(p.UnplayedBufferSize()); n > max {
			n = max
		}
		n2, err := p.src.Read(buf[:n])
		if err != nil && err != io.EOF {
			p.setError(err)
			return
		}
		if n > 0 {
			p.write(dst, buf[:n2])
		}

		if err == io.EOF {
			p.close(false)
			return
		}
	}
}
<commit_msg>audio/internal/go2cpp: Protect the functions by the lock correctly<commit_after>// Copyright 2021 The Ebiten 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 go2cpp

import (
	"io"
	"runtime"
	"sync"
	"syscall/js"
)

const (
	readChunkSize = 4096
)

type Context struct {
	v               js.Value
	sampleRate      int
	channelNum      int
	bitDepthInBytes int
}

func NewContext(sampleRate int, channelNum, bitDepthInBytes int) *Context {
	v := js.Global().Get("go2cpp").Call("createAudio", sampleRate, channelNum, bitDepthInBytes)
	return &Context{
		v:               v,
		sampleRate:      sampleRate,
		channelNum:      channelNum,
		bitDepthInBytes: bitDepthInBytes,
	}
}

func (c *Context) NewPlayer(r io.Reader) *Player {
	cond := sync.NewCond(&sync.Mutex{})
	onwritten := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
		cond.Signal()
		return nil
	})
	p := &Player{
		context:   c,
		src:       r,
		volume:    1,
		cond:      cond,
		onWritten: onwritten,
	}
	runtime.SetFinalizer(p, (*Player).Close)
	return p
}

func (c *Context) Close() error {
	return nil
}

func (c *Context) oneBufferSize() int {
	// TODO: This must be audio.oneBufferSize(p.context.sampleRate). Avoid the duplication.
	return c.sampleRate * c.channelNum * c.bitDepthInBytes / 4
}

func (c *Context) MaxBufferSize() int {
	// TODO: This must be audio.maxBufferSize(p.context.sampleRate). Avoid the duplication.
	return c.oneBufferSize() * 2
}

type playerState int

const (
	playerStatePaused playerState = iota
	playerStatePlaying
	playerStateClosed
)

type Player struct {
	context *Context
	src     io.Reader
	v       js.Value
	state   playerState
	volume  float64
	cond    *sync.Cond
	err     error
	buf     []byte

	onWritten js.Func
}

func (p *Player) Pause() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return
	}
	if !p.v.Truthy() {
		return
	}

	p.v.Call("pause")
	p.state = playerStatePaused
	p.cond.Signal()
}

func (p *Player) Play() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return
	}

	var runloop bool
	if !p.v.Truthy() {
		p.v = p.context.v.Call("createPlayer", p.onWritten)
		p.v.Set("volume", p.volume)
		runloop = true
	}

	p.v.Call("play")

	// Prepare the first data as soon as possible, or the audio can get stuck.
	// TODO: Get the appropriate buffer size from the C++ side.
	if p.buf == nil {
		n := p.context.oneBufferSize()
		if max := p.context.MaxBufferSize() - int(p.UnplayedBufferSize()); n > max {
			n = max
		}
		p.buf = make([]byte, n)
	}
	n, err := p.src.Read(p.buf)
	if err != nil && err != io.EOF {
		p.setError(err)
		return
	}
	if n > 0 {
		dst := js.Global().Get("Uint8Array").New(n)
		p.writeImpl(dst, p.buf[:n])
	}

	if runloop {
		go p.loop()
	}
	p.state = playerStatePlaying
	p.cond.Signal()
}

func (p *Player) IsPlaying() bool {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	return p.state == playerStatePlaying
}

func (p *Player) Reset() {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return
	}
	p.state = playerStatePaused

	if !p.v.Truthy() {
		return
	}

	p.v.Call("close", true)
	p.v = js.Undefined()
	p.cond.Signal()
}

func (p *Player) Volume() float64 {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if !p.v.Truthy() {
		return p.volume
	}
	return p.v.Get("volume").Float()
}

func (p *Player) SetVolume(volume float64) {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if !p.v.Truthy() {
		return
	}
	p.v.Set("volume", volume)
	p.volume = volume
}

func (p *Player) UnplayedBufferSize() int64 {
	if !p.v.Truthy() {
		return 0
	}
	return int64(p.v.Get("unplayedBufferSize").Int())
}

func (p *Player) Err() error {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	return p.err
}

func (p *Player) Close() error {
	runtime.SetFinalizer(p, nil)
	return p.close(true)
}

func (p *Player) close(remove bool) error {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state == playerStateClosed {
		return p.err
	}

	if p.v.Truthy() {
		p.v.Call("close", false)
		p.v = js.Undefined()
	}
	if remove {
		p.state = playerStateClosed
		p.onWritten.Release()
	} else {
		p.state = playerStatePaused
	}
	p.cond.Signal()
	return p.err
}

func (p *Player) setError(err error) {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	if p.state != playerStateClosed && p.v.Truthy() {
		p.v.Call("close", true)
		p.v = js.Undefined()
	}
	p.err = err
	p.state = playerStateClosed
	p.cond.Signal()
}

func (p *Player) shouldWait() bool {
	if !p.v.Truthy() {
		return false
	}
	switch p.state {
	case playerStatePaused:
		return true
	case playerStatePlaying:
		return p.v.Get("unplayedBufferSize").Int() >= p.context.MaxBufferSize()
	}
	return false
}

func (p *Player) waitUntilUnpaused() bool {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()

	for p.shouldWait() {
		p.cond.Wait()
	}
	return p.v.Truthy() && p.state == playerStatePlaying
}

func (p *Player) write(dst js.Value, src []byte) {
	p.cond.L.Lock()
	defer p.cond.L.Unlock()
	p.writeImpl(dst, src)
}

func (p *Player) writeImpl(dst js.Value, src []byte) {
	if p.state == playerStateClosed {
		return
	}
	if !p.v.Truthy() {
		return
	}

	js.CopyBytesToJS(dst, src)
	p.v.Call("write", dst, len(src))
}

func (p *Player) loop() {
	buf := make([]byte, readChunkSize)
	dst := js.Global().Get("Uint8Array").New(readChunkSize)

	for {
		if !p.waitUntilUnpaused() {
			return
		}

		n := readChunkSize
		if max := p.context.MaxBufferSize() - int(p.UnplayedBufferSize()); n > max {
			n = max
		}
		n2, err := p.src.Read(buf[:n])
		if err != nil && err != io.EOF {
			p.setError(err)
			return
		}
		if n > 0 {
			p.write(dst, buf[:n2])
		}

		if err == io.EOF {
			p.close(false)
			return
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2014 Caleb Brose, Chris Fogerty, Rob Sheehy, Zach Taylor, Nick Miller
//
// 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 main

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

    "github.com/mgutz/ansi"

    "github.com/zenazn/goji/web"
    "github.com/zenazn/goji/graceful"
    "github.com/zenazn/goji/web/middleware"

    "github.com/lighthouse/beacon/auth"
    "github.com/lighthouse/beacon/drivers"
    "github.com/lighthouse/beacon/structs"
)

var pemFile = flag.String("pem", "", "Path to Cert file")
var keyFile = flag.String("key", "", "Path to Key file")
var address = flag.String("h", "127.0.0.1:5000", "Address to host under")

var App *web.Mux
var Driver *structs.Driver

func init() {
    App = web.New()
    App.Use(middleware.Logger)
    App.Use(auth.Middleware)

    App.Handle("/d/*", func(c web.C, w http.ResponseWriter, r *http.Request) {
        target := fmt.Sprintf("http://%s",
            strings.SplitN(r.URL.Path, "/", 3)[2])

        req, err := http.NewRequest(r.Method, target, r.Body)
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        contentType := r.Header.Get("Content-Type")
        if contentType != "" {
            req.Header.Set("Content-Type", contentType)
        }

        resp, err := http.DefaultClient.Do(req)

        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        body, err := ioutil.ReadAll(resp.Body)

        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        w.WriteHeader(resp.StatusCode)
        w.Write(body)
    })

    App.Get("/vms", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.GetVMs())
        w.Write(response)
    })

    App.Get("/which", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.Name)
        w.Write(response)
    })

    App.Compile()
}

func main() {
    log.Printf(ansi.Color("Starting Beacon...", "white+b"))

    if !flag.Parsed() {
        flag.Parse()
    }

    Driver = drivers.Decide()

    log.Printf("Provider Interface: %s\n", ansi.Color(Driver.Name, "cyan+b"))
    log.Printf("Authentication Token: %s\n", ansi.Color(*auth.Token, "cyan+b"))

    graceful.HandleSignals()

    graceful.PreHook(func() {
        log.Printf(ansi.Color("Gracefully Shutting Down...", "white+b"))
    })
    graceful.PostHook(func() {
        log.Printf(ansi.Color("Done!", "white+b"))
    })

    defer graceful.Wait()

    http.Handle("/", App)
    log.Printf("Listening on %s", *address)

    var err error

    if *pemFile != "" && *keyFile != "" {
        log.Printf("Setting up secure server...")
        err = graceful.ListenAndServeTLS(*address, *pemFile, *keyFile, http.DefaultServeMux)
    } else {
        log.Printf(ansi.Color("Setting up unsecure server...", "yellow+b"))
        err = graceful.ListenAndServe(*address, http.DefaultServeMux)
    }

    if err != nil {
        log.Fatal(err)
    }
}
<commit_msg>Split on URL string rather than path<commit_after>// Copyright 2014 Caleb Brose, Chris Fogerty, Rob Sheehy, Zach Taylor, Nick Miller
//
// 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 main

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

    "github.com/mgutz/ansi"

    "github.com/zenazn/goji/web"
    "github.com/zenazn/goji/graceful"
    "github.com/zenazn/goji/web/middleware"

    "github.com/lighthouse/beacon/auth"
    "github.com/lighthouse/beacon/drivers"
    "github.com/lighthouse/beacon/structs"
)

var pemFile = flag.String("pem", "", "Path to Cert file")
var keyFile = flag.String("key", "", "Path to Key file")
var address = flag.String("h", "127.0.0.1:5000", "Address to host under")

var App *web.Mux
var Driver *structs.Driver

func init() {
    App = web.New()
    App.Use(middleware.Logger)
    App.Use(auth.Middleware)

    App.Handle("/d/*", func(c web.C, w http.ResponseWriter, r *http.Request) {
        target := fmt.Sprintf("http://%s",
            strings.SplitN(r.URL.String(), "/", 3)[2])

        req, err := http.NewRequest(r.Method, target, r.Body)
        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        contentType := r.Header.Get("Content-Type")
        if contentType != "" {
            req.Header.Set("Content-Type", contentType)
        }

        resp, err := http.DefaultClient.Do(req)

        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        body, err := ioutil.ReadAll(resp.Body)

        if err != nil {
            w.WriteHeader(http.StatusInternalServerError)
            fmt.Fprint(w, err)
            return
        }

        w.WriteHeader(resp.StatusCode)
        w.Write(body)
    })

    App.Get("/vms", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.GetVMs())
        w.Write(response)
    })

    App.Get("/which", func(c web.C, w http.ResponseWriter, r *http.Request) {
        response, _ := json.Marshal(Driver.Name)
        w.Write(response)
    })

    App.Compile()
}

func main() {
    log.Printf(ansi.Color("Starting Beacon...", "white+b"))

    if !flag.Parsed() {
        flag.Parse()
    }

    Driver = drivers.Decide()

    log.Printf("Provider Interface: %s\n", ansi.Color(Driver.Name, "cyan+b"))
    log.Printf("Authentication Token: %s\n", ansi.Color(*auth.Token, "cyan+b"))

    graceful.HandleSignals()

    graceful.PreHook(func() {
        log.Printf(ansi.Color("Gracefully Shutting Down...", "white+b"))
    })
    graceful.PostHook(func() {
        log.Printf(ansi.Color("Done!", "white+b"))
    })

    defer graceful.Wait()

    http.Handle("/", App)
    log.Printf("Listening on %s", *address)

    var err error

    if *pemFile != "" && *keyFile != "" {
        log.Printf("Setting up secure server...")
        err = graceful.ListenAndServeTLS(*address, *pemFile, *keyFile, http.DefaultServeMux)
    } else {
        log.Printf(ansi.Color("Setting up unsecure server...", "yellow+b"))
        err = graceful.ListenAndServe(*address, http.DefaultServeMux)
    }

    if err != nil {
        log.Fatal(err)
    }
}
<|endoftext|>


<commit_before>package edit

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

	"github.com/elves/elvish/edit/uitypes"
	"github.com/elves/elvish/util"
)

// Completion subsystem.

// Interface.

type completion struct {
	completer  string
	begin, end int
	all        []*candidate

	filtering       bool
	filter          string
	candidates      []*candidate
	selected        int
	firstShown      int
	lastShownInFull int
	height          int
}

func (*completion) Mode() ModeType {
	return modeCompletion
}

func (c *completion) needScrollbar() bool {
	return c.firstShown > 0 || c.lastShownInFull < len(c.candidates)-1
}

func (c *completion) ModeLine() renderer {
	ml := modeLineRenderer{fmt.Sprintf(" COMPLETING %s ", c.completer), c.filter}
	if !c.needScrollbar() {
		return ml
	}
	return modeLineWithScrollBarRenderer{ml,
		len(c.candidates), c.firstShown, c.lastShownInFull + 1}
}

func (c *completion) CursorOnModeLine() bool {
	return c.filtering
}

func startCompl(ed *Editor) {
	startCompletionInner(ed, false)
}

func complPrefixOrStartCompl(ed *Editor) {
	startCompletionInner(ed, true)
}

func complUp(ed *Editor) {
	ed.completion.prev(false)
}

func complDown(ed *Editor) {
	ed.completion.next(false)
}

func complLeft(ed *Editor) {
	if c := ed.completion.selected - ed.completion.height; c >= 0 {
		ed.completion.selected = c
	}
}

func complRight(ed *Editor) {
	if c := ed.completion.selected + ed.completion.height; c < len(ed.completion.candidates) {
		ed.completion.selected = c
	}
}

func complDownCycle(ed *Editor) {
	ed.completion.next(true)
}

// acceptCompletion accepts currently selected completion candidate.
func complAccept(ed *Editor) {
	c := ed.completion
	if 0 <= c.selected && c.selected < len(c.candidates) {
		ed.line, ed.dot = c.apply(ed.line, ed.dot)
	}
	ed.mode = &ed.insert
}

func complDefault(ed *Editor) {
	k := ed.lastKey
	c := &ed.completion
	if c.filtering && likeChar(k) {
		c.changeFilter(c.filter + string(k.Rune))
	} else if c.filtering && k == (uitypes.Key{uitypes.Backspace, 0}) {
		_, size := utf8.DecodeLastRuneInString(c.filter)
		if size > 0 {
			c.changeFilter(c.filter[:len(c.filter)-size])
		}
	} else {
		complAccept(ed)
		ed.nextAction = action{typ: reprocessKey}
	}
}

func complTriggerFilter(ed *Editor) {
	c := &ed.completion
	if c.filtering {
		c.filtering = false
		c.changeFilter("")
	} else {
		c.filtering = true
	}
}

func (comp *completion) selectedCandidate() *candidate {
	if comp.selected == -1 {
		return &candidate{}
	}
	return comp.candidates[comp.selected]
}

// apply returns the line and dot after applying a candidate.
func (comp *completion) apply(line string, dot int) (string, int) {
	text := comp.selectedCandidate().text
	return line[:comp.begin] + text + line[comp.end:], comp.begin + len(text)
}

func (c *completion) prev(cycle bool) {
	c.selected--
	if c.selected == -1 {
		if cycle {
			c.selected = len(c.candidates) - 1
		} else {
			c.selected++
		}
	}
}

func (c *completion) next(cycle bool) {
	c.selected++
	if c.selected == len(c.candidates) {
		if cycle {
			c.selected = 0
		} else {
			c.selected--
		}
	}
}

func startCompletionInner(ed *Editor, acceptPrefix bool) {
	node := findLeafNode(ed.chunk, ed.dot)
	if node == nil {
		return
	}

	c := &completion{begin: -1}
	for _, item := range completers {
		compl, err := item.completer(node, ed.evaler)
		if compl != nil {
			c.completer = item.name
			c.begin, c.end, c.all = compl.begin, compl.end, compl.cands
			c.candidates = c.all
			break
		} else if err != nil && err != errCompletionUnapplicable {
			ed.Notify("%v", err)
		}
	}

	if c.begin < 0 {
		ed.addTip("unsupported completion :(")
		Logger.Println("path to current leaf, leaf first")
		for n := node; n != nil; n = n.Parent() {
			Logger.Printf("%T (%d-%d)", n, n.Begin(), n.End())
		}
	} else if len(c.candidates) == 0 {
		ed.addTip("no candidate for %s", c.completer)
	} else {
		if acceptPrefix {
			// If there is a non-empty longest common prefix, insert it and
			// don't start completion mode.
			//
			// As a special case, when there is exactly one candidate, it is
			// immeidately accepted.
			prefix := c.candidates[0].text
			for _, cand := range c.candidates[1:] {
				prefix = commonPrefix(prefix, cand.text)
				if prefix == "" {
					break
				}
			}
			if prefix != "" && prefix != ed.line[c.begin:c.end] {
				ed.line = ed.line[:c.begin] + prefix + ed.line[c.end:]
				ed.dot = c.begin + len(prefix)
				return
			}
		}
		ed.completion = *c
		ed.mode = &ed.completion
	}
}

// commonPrefix returns the longest common prefix of two strings.
func commonPrefix(s, t string) string {
	for i, r := range s {
		if i >= len(t) {
			return s[:i]
		}
		r2, _ := utf8.DecodeRuneInString(t[i:])
		if r2 != r {
			return s[:i]
		}
	}
	return s
}

const (
	completionColMarginLeft  = 1
	completionColMarginRight = 1
	completionColMarginTotal = completionColMarginLeft + completionColMarginRight
)

// maxWidth finds the maximum wcwidth of display texts of candidates [lo, hi).
// hi may be larger than the number of candidates, in which case it is truncated
// to the number of candidates.
func (comp *completion) maxWidth(lo, hi int) int {
	if hi > len(comp.candidates) {
		hi = len(comp.candidates)
	}
	width := 0
	for i := lo; i < hi; i++ {
		w := util.Wcswidth(comp.candidates[i].display.text)
		if width < w {
			width = w
		}
	}
	return width
}

func (comp *completion) ListRender(width, maxHeight int) *buffer {
	b := newBuffer(width)
	cands := comp.candidates
	if len(cands) == 0 {
		b.writes(util.TrimWcwidth("(no result)", width), "")
		return b
	}
	if maxHeight <= 1 || width <= 2 {
		b.writes(util.TrimWcwidth("(terminal too small)", width), "")
		return b
	}

	// Reserve the the rightmost row as margins.
	width -= 1

	// Determine comp.height and comp.firstShown.
	// First determine whether all candidates can be fit in the screen,
	// assuming that they are all of maximum width. If that is the case, we use
	// the computed height as the height for the listing, and the first
	// candidate to show is 0. Otherwise, we use min(height, len(cands)) as the
	// height and find the first candidate to show.
	perLine := max(1, width/(comp.maxWidth(0, len(cands))+completionColMarginTotal))
	heightBound := util.CeilDiv(len(cands), perLine)
	first := 0
	height := 0
	if heightBound < maxHeight {
		height = heightBound
	} else {
		height = min(maxHeight, len(cands))
		// Determine the first column to show. We start with the column in which the
		// selected one is found, moving to the left until either the width is
		// exhausted, or the old value of firstShown has been hit.
		first = comp.selected / height * height
		w := comp.maxWidth(first, first+height) + completionColMarginTotal
		for ; first > comp.firstShown; first -= height {
			dw := comp.maxWidth(first-height, first) + completionColMarginTotal
			if w+dw > width {
				break
			}
			w += dw
		}
	}
	comp.height = height
	comp.firstShown = first

	var i, j int
	remainedWidth := width
	trimmed := false
	// Show the results in columns, until width is exceeded.
	for i = first; i < len(cands); i += height {
		// Determine the width of the column (without the margin)
		colWidth := comp.maxWidth(i, min(i+height, len(cands)))
		totalColWidth := colWidth + completionColMarginTotal
		if totalColWidth > remainedWidth {
			totalColWidth = remainedWidth
			colWidth = totalColWidth - completionColMarginTotal
			trimmed = true
		}

		col := newBuffer(totalColWidth)
		for j = i; j < i+height; j++ {
			if j > i {
				col.newline()
			}
			if j >= len(cands) {
				// Write padding to make the listing a rectangle.
				col.writePadding(totalColWidth, styleForCompletion.String())
			} else {
				col.writePadding(completionColMarginLeft, styleForCompletion.String())
				s := joinStyles(styleForCompletion, cands[j].display.styles)
				if j == comp.selected {
					s = append(s, styleForSelectedCompletion.String())
				}
				col.writes(util.ForceWcwidth(cands[j].display.text, colWidth), s.String())
				col.writePadding(completionColMarginRight, styleForCompletion.String())
				if !trimmed {
					comp.lastShownInFull = j
				}
			}
		}

		b.extendHorizontal(col, 0)
		remainedWidth -= totalColWidth
		if remainedWidth <= completionColMarginTotal {
			break
		}
	}
	// When the listing is incomplete, always use up the entire width.
	if remainedWidth > 0 && comp.needScrollbar() {
		col := newBuffer(remainedWidth)
		for i := 0; i < height; i++ {
			if i > 0 {
				col.newline()
			}
			col.writePadding(remainedWidth, styleForCompletion.String())
		}
		b.extendHorizontal(col, 0)
		remainedWidth = 0
	}
	return b
}

func (c *completion) changeFilter(f string) {
	c.filter = f
	if f == "" {
		c.candidates = c.all
		return
	}
	c.candidates = nil
	for _, cand := range c.all {
		if strings.Contains(cand.display.text, f) {
			c.candidates = append(c.candidates, cand)
		}
	}
	if len(c.candidates) > 0 {
		c.selected = 0
	} else {
		c.selected = -1
	}
}
<commit_msg>Show completion error in tip, not in notification.<commit_after>package edit

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

	"github.com/elves/elvish/edit/uitypes"
	"github.com/elves/elvish/util"
)

// Completion subsystem.

// Interface.

type completion struct {
	completer  string
	begin, end int
	all        []*candidate

	filtering       bool
	filter          string
	candidates      []*candidate
	selected        int
	firstShown      int
	lastShownInFull int
	height          int
}

func (*completion) Mode() ModeType {
	return modeCompletion
}

func (c *completion) needScrollbar() bool {
	return c.firstShown > 0 || c.lastShownInFull < len(c.candidates)-1
}

func (c *completion) ModeLine() renderer {
	ml := modeLineRenderer{fmt.Sprintf(" COMPLETING %s ", c.completer), c.filter}
	if !c.needScrollbar() {
		return ml
	}
	return modeLineWithScrollBarRenderer{ml,
		len(c.candidates), c.firstShown, c.lastShownInFull + 1}
}

func (c *completion) CursorOnModeLine() bool {
	return c.filtering
}

func startCompl(ed *Editor) {
	startCompletionInner(ed, false)
}

func complPrefixOrStartCompl(ed *Editor) {
	startCompletionInner(ed, true)
}

func complUp(ed *Editor) {
	ed.completion.prev(false)
}

func complDown(ed *Editor) {
	ed.completion.next(false)
}

func complLeft(ed *Editor) {
	if c := ed.completion.selected - ed.completion.height; c >= 0 {
		ed.completion.selected = c
	}
}

func complRight(ed *Editor) {
	if c := ed.completion.selected + ed.completion.height; c < len(ed.completion.candidates) {
		ed.completion.selected = c
	}
}

func complDownCycle(ed *Editor) {
	ed.completion.next(true)
}

// acceptCompletion accepts currently selected completion candidate.
func complAccept(ed *Editor) {
	c := ed.completion
	if 0 <= c.selected && c.selected < len(c.candidates) {
		ed.line, ed.dot = c.apply(ed.line, ed.dot)
	}
	ed.mode = &ed.insert
}

func complDefault(ed *Editor) {
	k := ed.lastKey
	c := &ed.completion
	if c.filtering && likeChar(k) {
		c.changeFilter(c.filter + string(k.Rune))
	} else if c.filtering && k == (uitypes.Key{uitypes.Backspace, 0}) {
		_, size := utf8.DecodeLastRuneInString(c.filter)
		if size > 0 {
			c.changeFilter(c.filter[:len(c.filter)-size])
		}
	} else {
		complAccept(ed)
		ed.nextAction = action{typ: reprocessKey}
	}
}

func complTriggerFilter(ed *Editor) {
	c := &ed.completion
	if c.filtering {
		c.filtering = false
		c.changeFilter("")
	} else {
		c.filtering = true
	}
}

func (comp *completion) selectedCandidate() *candidate {
	if comp.selected == -1 {
		return &candidate{}
	}
	return comp.candidates[comp.selected]
}

// apply returns the line and dot after applying a candidate.
func (comp *completion) apply(line string, dot int) (string, int) {
	text := comp.selectedCandidate().text
	return line[:comp.begin] + text + line[comp.end:], comp.begin + len(text)
}

func (c *completion) prev(cycle bool) {
	c.selected--
	if c.selected == -1 {
		if cycle {
			c.selected = len(c.candidates) - 1
		} else {
			c.selected++
		}
	}
}

func (c *completion) next(cycle bool) {
	c.selected++
	if c.selected == len(c.candidates) {
		if cycle {
			c.selected = 0
		} else {
			c.selected--
		}
	}
}

func startCompletionInner(ed *Editor, acceptPrefix bool) {
	node := findLeafNode(ed.chunk, ed.dot)
	if node == nil {
		return
	}

	c := &completion{begin: -1}
	shownError := false
	for _, item := range completers {
		compl, err := item.completer(node, ed.evaler)
		if compl != nil {
			c.completer = item.name
			c.begin, c.end, c.all = compl.begin, compl.end, compl.cands
			c.candidates = c.all
			break
		} else if err != nil && err != errCompletionUnapplicable {
			ed.addTip("%v", err)
			shownError = true
			break
		}
	}

	if c.begin < 0 {
		if !shownError {
			ed.addTip("unsupported completion :(")
		}
		Logger.Println("path to current leaf, leaf first")
		for n := node; n != nil; n = n.Parent() {
			Logger.Printf("%T (%d-%d)", n, n.Begin(), n.End())
		}
	} else if len(c.candidates) == 0 {
		ed.addTip("no candidate for %s", c.completer)
	} else {
		if acceptPrefix {
			// If there is a non-empty longest common prefix, insert it and
			// don't start completion mode.
			//
			// As a special case, when there is exactly one candidate, it is
			// immeidately accepted.
			prefix := c.candidates[0].text
			for _, cand := range c.candidates[1:] {
				prefix = commonPrefix(prefix, cand.text)
				if prefix == "" {
					break
				}
			}
			if prefix != "" && prefix != ed.line[c.begin:c.end] {
				ed.line = ed.line[:c.begin] + prefix + ed.line[c.end:]
				ed.dot = c.begin + len(prefix)
				return
			}
		}
		ed.completion = *c
		ed.mode = &ed.completion
	}
}

// commonPrefix returns the longest common prefix of two strings.
func commonPrefix(s, t string) string {
	for i, r := range s {
		if i >= len(t) {
			return s[:i]
		}
		r2, _ := utf8.DecodeRuneInString(t[i:])
		if r2 != r {
			return s[:i]
		}
	}
	return s
}

const (
	completionColMarginLeft  = 1
	completionColMarginRight = 1
	completionColMarginTotal = completionColMarginLeft + completionColMarginRight
)

// maxWidth finds the maximum wcwidth of display texts of candidates [lo, hi).
// hi may be larger than the number of candidates, in which case it is truncated
// to the number of candidates.
func (comp *completion) maxWidth(lo, hi int) int {
	if hi > len(comp.candidates) {
		hi = len(comp.candidates)
	}
	width := 0
	for i := lo; i < hi; i++ {
		w := util.Wcswidth(comp.candidates[i].display.text)
		if width < w {
			width = w
		}
	}
	return width
}

func (comp *completion) ListRender(width, maxHeight int) *buffer {
	b := newBuffer(width)
	cands := comp.candidates
	if len(cands) == 0 {
		b.writes(util.TrimWcwidth("(no result)", width), "")
		return b
	}
	if maxHeight <= 1 || width <= 2 {
		b.writes(util.TrimWcwidth("(terminal too small)", width), "")
		return b
	}

	// Reserve the the rightmost row as margins.
	width -= 1

	// Determine comp.height and comp.firstShown.
	// First determine whether all candidates can be fit in the screen,
	// assuming that they are all of maximum width. If that is the case, we use
	// the computed height as the height for the listing, and the first
	// candidate to show is 0. Otherwise, we use min(height, len(cands)) as the
	// height and find the first candidate to show.
	perLine := max(1, width/(comp.maxWidth(0, len(cands))+completionColMarginTotal))
	heightBound := util.CeilDiv(len(cands), perLine)
	first := 0
	height := 0
	if heightBound < maxHeight {
		height = heightBound
	} else {
		height = min(maxHeight, len(cands))
		// Determine the first column to show. We start with the column in which the
		// selected one is found, moving to the left until either the width is
		// exhausted, or the old value of firstShown has been hit.
		first = comp.selected / height * height
		w := comp.maxWidth(first, first+height) + completionColMarginTotal
		for ; first > comp.firstShown; first -= height {
			dw := comp.maxWidth(first-height, first) + completionColMarginTotal
			if w+dw > width {
				break
			}
			w += dw
		}
	}
	comp.height = height
	comp.firstShown = first

	var i, j int
	remainedWidth := width
	trimmed := false
	// Show the results in columns, until width is exceeded.
	for i = first; i < len(cands); i += height {
		// Determine the width of the column (without the margin)
		colWidth := comp.maxWidth(i, min(i+height, len(cands)))
		totalColWidth := colWidth + completionColMarginTotal
		if totalColWidth > remainedWidth {
			totalColWidth = remainedWidth
			colWidth = totalColWidth - completionColMarginTotal
			trimmed = true
		}

		col := newBuffer(totalColWidth)
		for j = i; j < i+height; j++ {
			if j > i {
				col.newline()
			}
			if j >= len(cands) {
				// Write padding to make the listing a rectangle.
				col.writePadding(totalColWidth, styleForCompletion.String())
			} else {
				col.writePadding(completionColMarginLeft, styleForCompletion.String())
				s := joinStyles(styleForCompletion, cands[j].display.styles)
				if j == comp.selected {
					s = append(s, styleForSelectedCompletion.String())
				}
				col.writes(util.ForceWcwidth(cands[j].display.text, colWidth), s.String())
				col.writePadding(completionColMarginRight, styleForCompletion.String())
				if !trimmed {
					comp.lastShownInFull = j
				}
			}
		}

		b.extendHorizontal(col, 0)
		remainedWidth -= totalColWidth
		if remainedWidth <= completionColMarginTotal {
			break
		}
	}
	// When the listing is incomplete, always use up the entire width.
	if remainedWidth > 0 && comp.needScrollbar() {
		col := newBuffer(remainedWidth)
		for i := 0; i < height; i++ {
			if i > 0 {
				col.newline()
			}
			col.writePadding(remainedWidth, styleForCompletion.String())
		}
		b.extendHorizontal(col, 0)
		remainedWidth = 0
	}
	return b
}

func (c *completion) changeFilter(f string) {
	c.filter = f
	if f == "" {
		c.candidates = c.all
		return
	}
	c.candidates = nil
	for _, cand := range c.all {
		if strings.Contains(cand.display.text, f) {
			c.candidates = append(c.candidates, cand)
		}
	}
	if len(c.candidates) > 0 {
		c.selected = 0
	} else {
		c.selected = -1
	}
}
<|endoftext|>


<commit_before>package kateway

import (
	"fmt"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/funkygao/gafka/cmd/kateway/api/v1"
	"github.com/funkygao/gafka/cmd/kguard/monitor"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/go-metrics"
	log "github.com/funkygao/log4go"
)

func init() {
	monitor.RegisterWatcher("kateway.pubsub", func() monitor.Watcher {
		return &WatchPubsub{
			Tick: time.Minute,
		}
	})
}

// WatchPubsub monitors aliveness of kateway cluster.
type WatchPubsub struct {
	Zkzone *zk.ZkZone
	Stop   <-chan struct{}
	Tick   time.Duration
	Wg     *sync.WaitGroup

	startedAt time.Time
	seq       int

	pubLatency, subLatency metrics.Histogram
}

func (this *WatchPubsub) Init(ctx monitor.Context) {
	this.Zkzone = ctx.ZkZone()
	this.Stop = ctx.StopChan()
	this.Wg = ctx.Inflight()
}

func (this *WatchPubsub) Run() {
	defer this.Wg.Done()

	ticker := time.NewTicker(this.Tick)
	defer ticker.Stop()

	this.startedAt = time.Now()
	pubsubHealth := metrics.NewRegisteredGauge("kateway.pubsub.fail", nil)
	this.pubLatency = metrics.NewRegisteredHistogram("kateway.pubsub.latency.pub", nil, metrics.NewExpDecaySample(1028, 0.015))
	this.subLatency = metrics.NewRegisteredHistogram("kateway.pubsub.latency.sub", nil, metrics.NewExpDecaySample(1028, 0.015))

	for {
		select {
		case <-this.Stop:
			log.Info("kateway.pubsub stopped")
			return

		case <-ticker.C:
			if err := this.runCheckup(); err != nil {
				pubsubHealth.Update(1)
			} else {
				pubsubHealth.Update(0)
			}
		}
	}
}

func (this *WatchPubsub) runCheckup() error {
	kws, err := this.Zkzone.KatewayInfos()
	if err != nil {
		log.Error("pubsub: %v", err)
		return err
	}

	var (
		myApp  = os.Getenv("MYAPP")
		hisApp = os.Getenv("HISAPP")
		secret = os.Getenv("APPKEY")
		ver    = "v1"
		topic  = "smoketestonly"
		group  = "__smoketestonly__"

		pubEndpoint = os.Getenv("PUB")
		subEndpoint = os.Getenv("SUB")
	)

	if myApp == "" || hisApp == "" || secret == "" {
		log.Error("empty pubsub params provided")
		return nil
	}

	if pubEndpoint != "" && subEndpoint != "" {
		// add the load balancer endpoint
		kws = append(kws, &zk.KatewayMeta{
			Id:      "0",
			PubAddr: pubEndpoint,
			SubAddr: subEndpoint,
		})
	}

	for _, kw := range kws {
		// pub a message
		cf := api.DefaultConfig(myApp, secret)
		cf.Pub.Endpoint = kw.PubAddr
		cf.Sub.Endpoint = kw.SubAddr
		cli := api.NewClient(cf)
		this.seq++
		pubMsg := fmt.Sprintf("kguard smoke test msg: [%s/%d]", this.startedAt, this.seq)

		t0 := time.Now()
		err = cli.Pub("", []byte(pubMsg), api.PubOption{
			Topic: topic,
			Ver:   ver,
		})
		if err != nil {
			log.Error("pub[%s]: %v", kw.Id, err)
			return err
		}
		this.pubLatency.Update(time.Since(t0).Nanoseconds() / 1e6) // in ms

		t0 = time.Now()

		// confirm that sub can get the pub'ed message
		err = cli.Sub(api.SubOption{
			AppId:     hisApp,
			Topic:     topic,
			Ver:       ver,
			Group:     group,
			AutoClose: true,
		}, func(statusCode int, subMsg []byte) error {
			if statusCode != http.StatusOK {
				return fmt.Errorf("unexpected http status: %s", http.StatusText(statusCode))
			}
			if len(subMsg) < 10 {
				log.Warn("unexpected sub msg: %s", string(subMsg))
			}

			return api.ErrSubStop
		})
		if err != nil {
			log.Error("sub[%s]: %v", kw.Id, err)
			return err
		}

		this.subLatency.Update(time.Since(t0).Nanoseconds() / 1e6) // in ms

		// wait for server cleanup the sub conn
		time.Sleep(time.Second)
	}

	return nil
}
<commit_msg>kguard report PubSub fail if no kateway instances found<commit_after>package kateway

import (
	"fmt"
	"net/http"
	"os"
	"sync"
	"time"

	"github.com/funkygao/gafka/cmd/kateway/api/v1"
	"github.com/funkygao/gafka/cmd/kguard/monitor"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/go-metrics"
	log "github.com/funkygao/log4go"
)

var errKatewayAllGone = fmt.Errorf("all kateway gone")

func init() {
	monitor.RegisterWatcher("kateway.pubsub", func() monitor.Watcher {
		return &WatchPubsub{
			Tick: time.Minute,
		}
	})
}

// WatchPubsub monitors aliveness of kateway cluster.
type WatchPubsub struct {
	Zkzone *zk.ZkZone
	Stop   <-chan struct{}
	Tick   time.Duration
	Wg     *sync.WaitGroup

	startedAt time.Time
	seq       int

	pubLatency, subLatency metrics.Histogram
}

func (this *WatchPubsub) Init(ctx monitor.Context) {
	this.Zkzone = ctx.ZkZone()
	this.Stop = ctx.StopChan()
	this.Wg = ctx.Inflight()
}

func (this *WatchPubsub) Run() {
	defer this.Wg.Done()

	ticker := time.NewTicker(this.Tick)
	defer ticker.Stop()

	this.startedAt = time.Now()
	pubsubHealth := metrics.NewRegisteredGauge("kateway.pubsub.fail", nil)
	this.pubLatency = metrics.NewRegisteredHistogram("kateway.pubsub.latency.pub", nil, metrics.NewExpDecaySample(1028, 0.015))
	this.subLatency = metrics.NewRegisteredHistogram("kateway.pubsub.latency.sub", nil, metrics.NewExpDecaySample(1028, 0.015))

	for {
		select {
		case <-this.Stop:
			log.Info("kateway.pubsub stopped")
			return

		case <-ticker.C:
			if err := this.runCheckup(); err != nil {
				pubsubHealth.Update(1)
			} else {
				pubsubHealth.Update(0)
			}
		}
	}
}

func (this *WatchPubsub) runCheckup() error {
	kws, err := this.Zkzone.KatewayInfos()
	if err != nil {
		log.Error("pubsub: %v", err)
		return err
	}

	if len(kws) == 0 {
		log.Error("%s", errKatewayAllGone)
		return errKatewayAllGone
	}

	var (
		myApp  = os.Getenv("MYAPP")
		hisApp = os.Getenv("HISAPP")
		secret = os.Getenv("APPKEY")
		ver    = "v1"
		topic  = "smoketestonly"
		group  = "__smoketestonly__"

		pubEndpoint = os.Getenv("PUB")
		subEndpoint = os.Getenv("SUB")
	)

	if myApp == "" || hisApp == "" || secret == "" {
		log.Error("empty pubsub params provided")
		return nil
	}

	if pubEndpoint != "" && subEndpoint != "" {
		// add the load balancer endpoint
		kws = append(kws, &zk.KatewayMeta{
			Id:      "0",
			PubAddr: pubEndpoint,
			SubAddr: subEndpoint,
		})
	}

	for _, kw := range kws {
		// pub a message
		cf := api.DefaultConfig(myApp, secret)
		cf.Pub.Endpoint = kw.PubAddr
		cf.Sub.Endpoint = kw.SubAddr
		cli := api.NewClient(cf)
		this.seq++
		pubMsg := fmt.Sprintf("kguard smoke test msg: [%s/%d]", this.startedAt, this.seq)

		t0 := time.Now()
		err = cli.Pub("", []byte(pubMsg), api.PubOption{
			Topic: topic,
			Ver:   ver,
		})
		if err != nil {
			log.Error("pub[%s]: %v", kw.Id, err)
			return err
		}
		this.pubLatency.Update(time.Since(t0).Nanoseconds() / 1e6) // in ms

		t0 = time.Now()

		// confirm that sub can get the pub'ed message
		err = cli.Sub(api.SubOption{
			AppId:     hisApp,
			Topic:     topic,
			Ver:       ver,
			Group:     group,
			AutoClose: true,
		}, func(statusCode int, subMsg []byte) error {
			if statusCode != http.StatusOK {
				return fmt.Errorf("unexpected http status: %s", http.StatusText(statusCode))
			}
			if len(subMsg) < 10 {
				log.Warn("unexpected sub msg: %s", string(subMsg))
			}

			return api.ErrSubStop
		})
		if err != nil {
			log.Error("sub[%s]: %v", kw.Id, err)
			return err
		}

		this.subLatency.Update(time.Since(t0).Nanoseconds() / 1e6) // in ms

		// wait for server cleanup the sub conn
		time.Sleep(time.Second)
	}

	return nil
}
<|endoftext|>


<commit_before>package filesystem

import (
	"fmt"
	"io"
)

func (fs *FileSystem) debugWrite(w io.Writer, prefix string) error {
	return fs.Directory.debugWrite(w, prefix)
}

func (directory *Directory) debugWrite(w io.Writer, prefix string) error {
	_, err := fmt.Fprintf(w, "%s%s\n", prefix, directory.Name)
	if err != nil {
		return err
	}
	if len(directory.RegularFileList) > 0 {
		_, err = fmt.Fprintf(w, "%s Regular Files:\n", prefix)
		if err != nil {
			return err
		}
		for _, file := range directory.RegularFileList {
			err = file.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	if len(directory.SymlinkList) > 0 {
		_, err = fmt.Fprintf(w, "%s Symlinks:\n", prefix)
		if err != nil {
			return err
		}
		for _, symlink := range directory.SymlinkList {
			err = symlink.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	if len(directory.FileList) > 0 {
		_, err = fmt.Fprintf(w, "%s Files:\n", prefix)
		if err != nil {
			return err
		}
		for _, file := range directory.FileList {
			err = file.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	if len(directory.DirectoryList) > 0 {
		_, err = fmt.Fprintf(w, "%s Directories:\n", prefix)
		if err != nil {
			return err
		}
		for _, dir := range directory.DirectoryList {
			err = dir.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (file *RegularFile) debugWrite(w io.Writer, prefix string) error {
	_, err := fmt.Fprintf(w, "%s%s\t%x\n", prefix, file.Name, file.inode.Hash)
	if err != nil {
		return err
	}
	return nil
}

func (symlink *Symlink) debugWrite(w io.Writer, prefix string) error {
	_, err := fmt.Fprintf(w, "%s%s\t%s\n", prefix, symlink.Name,
		symlink.inode.Symlink)
	if err != nil {
		return err
	}
	return nil
}

func (file *File) debugWrite(w io.Writer, prefix string) error {
	var data string
	data = ""
	_, err := fmt.Fprintf(w, "%s%s\t%s\n", prefix, file.Name, data)
	if err != nil {
		return err
	}
	return nil
}
<commit_msg>Add Mode, Uid and Gid to debugging output.<commit_after>package filesystem

import (
	"fmt"
	"io"
)

func (fs *FileSystem) debugWrite(w io.Writer, prefix string) error {
	return fs.Directory.debugWrite(w, prefix)
}

func (directory *Directory) debugWrite(w io.Writer, prefix string) error {
	_, err := fmt.Fprintf(w, "%s%s\t%o %d %d\n", prefix, directory.Name,
		directory.Mode, directory.Uid, directory.Gid)
	if err != nil {
		return err
	}
	if len(directory.RegularFileList) > 0 {
		_, err = fmt.Fprintf(w, "%s Regular Files:\n", prefix)
		if err != nil {
			return err
		}
		for _, file := range directory.RegularFileList {
			err = file.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	if len(directory.SymlinkList) > 0 {
		_, err = fmt.Fprintf(w, "%s Symlinks:\n", prefix)
		if err != nil {
			return err
		}
		for _, symlink := range directory.SymlinkList {
			err = symlink.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	if len(directory.FileList) > 0 {
		_, err = fmt.Fprintf(w, "%s Files:\n", prefix)
		if err != nil {
			return err
		}
		for _, file := range directory.FileList {
			err = file.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	if len(directory.DirectoryList) > 0 {
		_, err = fmt.Fprintf(w, "%s Directories:\n", prefix)
		if err != nil {
			return err
		}
		for _, dir := range directory.DirectoryList {
			err = dir.DebugWrite(w, prefix+"  ")
			if err != nil {
				return err
			}
		}
	}
	return nil
}

func (file *RegularFile) debugWrite(w io.Writer, prefix string) error {
	inode := file.inode
	_, err := fmt.Fprintf(w, "%s%s\t%o %d %d %x\n", prefix, file.Name,
		inode.Mode, inode.Uid, inode.Gid, inode.Hash)
	if err != nil {
		return err
	}
	return nil
}

func (symlink *Symlink) debugWrite(w io.Writer, prefix string) error {
	inode := symlink.inode
	_, err := fmt.Fprintf(w, "%s%s\t%d %d %s\n", prefix, symlink.Name,
		inode.Uid, inode.Gid, inode.Symlink)
	if err != nil {
		return err
	}
	return nil
}

func (file *File) debugWrite(w io.Writer, prefix string) error {
	inode := file.inode
	var data string
	data = ""
	_, err := fmt.Fprintf(w, "%s%s\t%o %d %d %s\n", prefix, file.Name,
		inode.Mode, inode.Uid, inode.Gid, data)
	if err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package integration_test

import (
	"encoding/gob"
	"net/http"
	"os"
	"os/exec"

	"github.com/concourse/atc/api/resources"
	thijack "github.com/concourse/turbine/api/hijack"
	"github.com/kr/pty"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"github.com/onsi/gomega/ghttp"
)

var _ = FDescribe("Hijacking", func() {
	var atcServer *ghttp.Server
	var hijacked <-chan struct{}

	BeforeEach(func() {
		atcServer = ghttp.NewServer()
		hijacked = nil

		os.Setenv("ATC_URL", atcServer.URL())
	})

	hijackHandler := func(didHijack chan<- struct{}) http.HandlerFunc {
		return ghttp.CombineHandlers(
			ghttp.VerifyRequest("POST", "/api/v1/builds/3/hijack"),
			func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(http.StatusOK)

				sconn, sbr, err := w.(http.Hijacker).Hijack()
				Ω(err).ShouldNot(HaveOccurred())

				defer sconn.Close()

				close(didHijack)

				decoder := gob.NewDecoder(sbr)

				var payload thijack.ProcessPayload

				err = decoder.Decode(&payload)
				Ω(err).ShouldNot(HaveOccurred())

				Ω(payload).Should(Equal(thijack.ProcessPayload{
					Stdin: []byte("marco"),
				}))

				_, err = sconn.Write([]byte("polo"))
				Ω(err).ShouldNot(HaveOccurred())
			},
		)
	}

	hijack := func(args ...string) {
		pty, tty, err := pty.Open()
		Ω(err).ShouldNot(HaveOccurred())

		flyCmd := exec.Command(flyPath, append([]string{"hijack"}, args...)...)
		flyCmd.Stdin = tty

		sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(hijacked).Should(BeClosed())

		_, err = pty.WriteString("marco")
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(sess).Should(gbytes.Say("polo"))

		err = pty.Close()
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(sess).Should(gexec.Exit(0))
	}

	Context("with no arguments", func() {
		BeforeEach(func() {
			didHijack := make(chan struct{})
			hijacked = didHijack

			atcServer.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest("GET", "/api/v1/builds"),
					ghttp.RespondWithJSONEncoded(200, []resources.Build{
						{ID: 3, Name: "3", Status: "started"},
						{ID: 2, Name: "2", Status: "started"},
						{ID: 1, Name: "1", Status: "finished"},
					}),
				),
				hijackHandler(didHijack),
			)
		})

		It("hijacks the most recent build", func() {
			hijack()
		})
	})

	Context("with a specific job", func() {
		Context("when the job has a next build", func() {
			BeforeEach(func() {
				didHijack := make(chan struct{})
				hijacked = didHijack

				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/jobs/some-job"),
						ghttp.RespondWithJSONEncoded(200, resources.Job{
							NextBuild: &resources.Build{
								ID:      3,
								Name:    "3",
								Status:  "started",
								JobName: "some-job",
							},
							FinishedBuild: &resources.Build{
								ID:      2,
								Name:    "2",
								Status:  "failed",
								JobName: "some-job",
							},
						}),
					),
					hijackHandler(didHijack),
				)
			})

			It("hijacks the job's next build", func() {
				hijack("--job", "some-job")
			})
		})

		Context("when the job only has a finished build", func() {
			BeforeEach(func() {
				didHijack := make(chan struct{})
				hijacked = didHijack

				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/jobs/some-job"),
						ghttp.RespondWithJSONEncoded(200, resources.Job{
							NextBuild: nil,
							FinishedBuild: &resources.Build{
								ID:      3,
								Name:    "3",
								Status:  "failed",
								JobName: "some-job",
							},
						}),
					),
					hijackHandler(didHijack),
				)
			})

			It("hijacks the job's finished build", func() {
				hijack("--job", "some-job")
			})
		})

		Context("with a specific build of the job", func() {
			BeforeEach(func() {
				didHijack := make(chan struct{})
				hijacked = didHijack

				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/jobs/some-job/builds/3"),
						ghttp.RespondWithJSONEncoded(200, resources.Build{
							ID:      3,
							Name:    "3",
							Status:  "failed",
							JobName: "some-job",
						}),
					),
					hijackHandler(didHijack),
				)
			})

			It("hijacks the given build", func() {
				hijack("--job", "some-job", "--build", "3")
			})
		})
	})
})
<commit_msg>remove accidental focus<commit_after>package integration_test

import (
	"encoding/gob"
	"net/http"
	"os"
	"os/exec"

	"github.com/concourse/atc/api/resources"
	thijack "github.com/concourse/turbine/api/hijack"
	"github.com/kr/pty"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
	"github.com/onsi/gomega/ghttp"
)

var _ = Describe("Hijacking", func() {
	var atcServer *ghttp.Server
	var hijacked <-chan struct{}

	BeforeEach(func() {
		atcServer = ghttp.NewServer()
		hijacked = nil

		os.Setenv("ATC_URL", atcServer.URL())
	})

	hijackHandler := func(didHijack chan<- struct{}) http.HandlerFunc {
		return ghttp.CombineHandlers(
			ghttp.VerifyRequest("POST", "/api/v1/builds/3/hijack"),
			func(w http.ResponseWriter, r *http.Request) {
				w.WriteHeader(http.StatusOK)

				sconn, sbr, err := w.(http.Hijacker).Hijack()
				Ω(err).ShouldNot(HaveOccurred())

				defer sconn.Close()

				close(didHijack)

				decoder := gob.NewDecoder(sbr)

				var payload thijack.ProcessPayload

				err = decoder.Decode(&payload)
				Ω(err).ShouldNot(HaveOccurred())

				Ω(payload).Should(Equal(thijack.ProcessPayload{
					Stdin: []byte("marco"),
				}))

				_, err = sconn.Write([]byte("polo"))
				Ω(err).ShouldNot(HaveOccurred())
			},
		)
	}

	hijack := func(args ...string) {
		pty, tty, err := pty.Open()
		Ω(err).ShouldNot(HaveOccurred())

		flyCmd := exec.Command(flyPath, append([]string{"hijack"}, args...)...)
		flyCmd.Stdin = tty

		sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(hijacked).Should(BeClosed())

		_, err = pty.WriteString("marco")
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(sess).Should(gbytes.Say("polo"))

		err = pty.Close()
		Ω(err).ShouldNot(HaveOccurred())

		Eventually(sess).Should(gexec.Exit(0))
	}

	Context("with no arguments", func() {
		BeforeEach(func() {
			didHijack := make(chan struct{})
			hijacked = didHijack

			atcServer.AppendHandlers(
				ghttp.CombineHandlers(
					ghttp.VerifyRequest("GET", "/api/v1/builds"),
					ghttp.RespondWithJSONEncoded(200, []resources.Build{
						{ID: 3, Name: "3", Status: "started"},
						{ID: 2, Name: "2", Status: "started"},
						{ID: 1, Name: "1", Status: "finished"},
					}),
				),
				hijackHandler(didHijack),
			)
		})

		It("hijacks the most recent build", func() {
			hijack()
		})
	})

	Context("with a specific job", func() {
		Context("when the job has a next build", func() {
			BeforeEach(func() {
				didHijack := make(chan struct{})
				hijacked = didHijack

				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/jobs/some-job"),
						ghttp.RespondWithJSONEncoded(200, resources.Job{
							NextBuild: &resources.Build{
								ID:      3,
								Name:    "3",
								Status:  "started",
								JobName: "some-job",
							},
							FinishedBuild: &resources.Build{
								ID:      2,
								Name:    "2",
								Status:  "failed",
								JobName: "some-job",
							},
						}),
					),
					hijackHandler(didHijack),
				)
			})

			It("hijacks the job's next build", func() {
				hijack("--job", "some-job")
			})
		})

		Context("when the job only has a finished build", func() {
			BeforeEach(func() {
				didHijack := make(chan struct{})
				hijacked = didHijack

				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/jobs/some-job"),
						ghttp.RespondWithJSONEncoded(200, resources.Job{
							NextBuild: nil,
							FinishedBuild: &resources.Build{
								ID:      3,
								Name:    "3",
								Status:  "failed",
								JobName: "some-job",
							},
						}),
					),
					hijackHandler(didHijack),
				)
			})

			It("hijacks the job's finished build", func() {
				hijack("--job", "some-job")
			})
		})

		Context("with a specific build of the job", func() {
			BeforeEach(func() {
				didHijack := make(chan struct{})
				hijacked = didHijack

				atcServer.AppendHandlers(
					ghttp.CombineHandlers(
						ghttp.VerifyRequest("GET", "/api/v1/jobs/some-job/builds/3"),
						ghttp.RespondWithJSONEncoded(200, resources.Build{
							ID:      3,
							Name:    "3",
							Status:  "failed",
							JobName: "some-job",
						}),
					),
					hijackHandler(didHijack),
				)
			})

			It("hijacks the given build", func() {
				hijack("--job", "some-job", "--build", "3")
			})
		})
	})
})
<|endoftext|>


<commit_before>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package all

// Register all the available providers.
import (
	_ "launchpad.net/juju-core/environs/azure"
	_ "launchpad.net/juju-core/environs/ec2"
	_ "launchpad.net/juju-core/environs/local"
	_ "launchpad.net/juju-core/environs/maas"
	_ "launchpad.net/juju-core/environs/openstack"
)
<commit_msg>[r=dave-cheney] Temporarily remove azure provider for the 1.11.3 release.<commit_after>// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package all

// Register all the available providers.
import (
	_ "launchpad.net/juju-core/environs/ec2"
	_ "launchpad.net/juju-core/environs/local"
	_ "launchpad.net/juju-core/environs/maas"
	_ "launchpad.net/juju-core/environs/openstack"
)
<|endoftext|>


<commit_before>/*

	gamepkg is a package that helps locate, validate, and modify game package
	imports.

*/
package gamepkg

import (
	"errors"
	"github.com/jkomoros/boardgame/boardgame-util/lib/path"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type Pkg struct {
	//Every contstructo sets absolutePath to something that at least exists on
	//disk.
	absolutePath         string
	importPath           string
	calculatedIsGamePkg  bool
	memoizedIsGamePkg    bool
	memoizedIsGamePkgErr error
}

//New is a wrapper around NewFromImport and NewFromPath. First, it tries to
//interpret the input as an import. If that files, tries to interpret it as a
//path (rel or absolute), and if that fails, bails.
func New(importOrPath string) (*Pkg, error) {
	pkg, err := NewFromImport(importOrPath)
	if err == nil {
		return pkg, nil
	}
	return NewFromPath(importOrPath)
}

//NewFromPath takes path (either relative or absolute path) and returns a new
//Pkg. Will error if the given path does not appear to denote a valid game
//package for any reason.
func NewFromPath(path string) (*Pkg, error) {

	if !filepath.IsAbs(path) {

		cwd, err := os.Getwd()

		if err != nil {
			return nil, errors.New("Couldn't get working directory: " + err.Error())
		}

		path = filepath.Join(cwd, path)
	}

	return newPkg(path, "")

}

//NewFromImport will return a new Pkg pointing to that import. Will error
//if the given path does not appear to denote a valid game package for any
//reason.
func NewFromImport(importPath string) (*Pkg, error) {

	absPath, err := path.AbsoluteGoPkgPath(importPath)

	if err != nil {
		return nil, errors.New("Absolute path couldn't be found: " + err.Error())
	}

	//If no error, then absPath must point to a valid thing

	return newPkg(absPath, importPath)

}

func newPkg(absPath, importPath string) (*Pkg, error) {
	result := &Pkg{
		absolutePath: absPath,
		importPath:   importPath,
	}

	if info, err := os.Stat(absPath); err != nil {
		return nil, errors.New("Path doesn't point to valid location on disk: " + err.Error())
	} else if !info.IsDir() {
		return nil, errors.New("Path points to an object but it's not a directory.")
	}

	if !result.goPkg() {
		return nil, errors.New(absPath + " denotes a folder with no go source files")
	}

	isGamePkg, err := result.isGamePkg()

	if !isGamePkg {
		return nil, errors.New(absPath + " was not a valid game package: " + err.Error())
	}

	return result, nil
}

//AbsolutePath returns the absolute path where the package in question resides
//on disk. All constructors will have errored if AbsolutePath doesn't at the
//very least point to a valid location on disk.
func (p *Pkg) AbsolutePath() string {
	return p.absolutePath
}

//ReadOnly returns true if the package appears to be in a read-only location
//(e.g. a cached module checkout)
func (p *Pkg) ReadOnly() bool {

	absPath := p.AbsolutePath()

	modulePath := filepath.Join(os.Getenv("GOPATH"), "pkg", "mod")

	//TODO: check the file permissions on package files to check

	return strings.Contains(absPath, modulePath)

}

//goPkg validates that the absolutePath denotes a package with at least one go
//file. If there's an error will default to false.
func (g *Pkg) goPkg() bool {

	infos, _ := ioutil.ReadDir(g.AbsolutePath())

	for _, info := range infos {
		if filepath.Ext(info.Name()) == ".go" {
			return true
		}
	}

	return false

}

//Import returns the string that could be used in your source to import this
//package.
func (p *Pkg) Import() (string, error) {
	//Calculate it if not already calculated (for example via NewFromImport constructor)
	if p.importPath == "" {

		goPkg, err := build.ImportDir(p.AbsolutePath(), 0)

		if err != nil {
			return "", errors.New("Couldn't read package: " + err.Error())
		}

		//TODO: factor this into a helper that also sets the package name in
		//case it's asked for later.
		p.importPath = goPkg.ImportPath
	}

	return p.importPath, nil
}

//isPkg verifies that the package appears to be a valid game package.
//Specifically it checks for
func (g *Pkg) isGamePkg() (bool, error) {
	if !g.calculatedIsGamePkg {
		g.memoizedIsGamePkg, g.memoizedIsGamePkgErr = g.calculateIsGamePkg()
	}
	return g.memoizedIsGamePkg, g.memoizedIsGamePkgErr
}

func (g *Pkg) calculateIsGamePkg() (bool, error) {
	pkgs, err := parser.ParseDir(token.NewFileSet(), g.AbsolutePath(), nil, 0)

	if err != nil {
		return false, errors.New("Couldn't parse folder: " + err.Error())
	}

	if len(pkgs) < 1 {
		return false, errors.New("No packages in that directory")
	}

	if len(pkgs) > 1 {
		return false, errors.New("More than one package in that directory")
	}

	var pkg *ast.Package

	for _, p := range pkgs {
		pkg = p
	}

	foundNewDelegate := false

	for _, file := range pkg.Files {
		for _, decl := range file.Decls {
			fun, ok := decl.(*ast.FuncDecl)
			if !ok {
				continue
			}

			if fun.Name.String() != "NewDelegate" {
				continue
			}

			//OK, it might be the function. Does it have the right signature?

			if fun.Recv != nil {
				return false, errors.New("NewDelegate had a receiver")
			}

			if fun.Type.Params.NumFields() > 0 {
				return false, errors.New("NewDelegate took more than 0 items")
			}

			if fun.Type.Results.NumFields() != 1 {
				return false, errors.New("NewDelegate didn't return exactly one item")
			}

			//TODO: check that the returned item implements
			//boardgame.GameDelegate.

			foundNewDelegate = true
			break

		}

		if foundNewDelegate {
			break
		}
	}

	if !foundNewDelegate {
		return false, errors.New("Couldn't find NewDelegate")
	}

	return true, nil
}
<commit_msg>Made documentation more clear with examples. Part of #694.<commit_after>/*

	gamepkg is a package that helps locate, validate, and modify game package
	imports.

*/
package gamepkg

import (
	"errors"
	"github.com/jkomoros/boardgame/boardgame-util/lib/path"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

type Pkg struct {
	//Every contstructo sets absolutePath to something that at least exists on
	//disk.
	absolutePath         string
	importPath           string
	calculatedIsGamePkg  bool
	memoizedIsGamePkg    bool
	memoizedIsGamePkgErr error
}

//New is a wrapper around NewFromImport and NewFromPath. First, it tries to
//interpret the input as an import. If that files, tries to interpret it as a
//path (rel or absolute), and if that fails, bails.
func New(importOrPath string) (*Pkg, error) {
	pkg, err := NewFromImport(importOrPath)
	if err == nil {
		return pkg, nil
	}
	return NewFromPath(importOrPath)
}

//NewFromPath takes path (either relative or absolute path) and returns a new
//Pkg. Will error if the given path does not appear to denote a valid game
//package for any reason.
func NewFromPath(path string) (*Pkg, error) {

	if !filepath.IsAbs(path) {

		cwd, err := os.Getwd()

		if err != nil {
			return nil, errors.New("Couldn't get working directory: " + err.Error())
		}

		path = filepath.Join(cwd, path)
	}

	return newPkg(path, "")

}

//NewFromImport will return a new Pkg pointing to that import. Will error
//if the given path does not appear to denote a valid game package for any
//reason.
func NewFromImport(importPath string) (*Pkg, error) {

	absPath, err := path.AbsoluteGoPkgPath(importPath)

	if err != nil {
		return nil, errors.New("Absolute path couldn't be found: " + err.Error())
	}

	//If no error, then absPath must point to a valid thing

	return newPkg(absPath, importPath)

}

func newPkg(absPath, importPath string) (*Pkg, error) {
	result := &Pkg{
		absolutePath: absPath,
		importPath:   importPath,
	}

	if info, err := os.Stat(absPath); err != nil {
		return nil, errors.New("Path doesn't point to valid location on disk: " + err.Error())
	} else if !info.IsDir() {
		return nil, errors.New("Path points to an object but it's not a directory.")
	}

	if !result.goPkg() {
		return nil, errors.New(absPath + " denotes a folder with no go source files")
	}

	isGamePkg, err := result.isGamePkg()

	if !isGamePkg {
		return nil, errors.New(absPath + " was not a valid game package: " + err.Error())
	}

	return result, nil
}

//AbsolutePath returns the absolute path where the package in question resides
//on disk. All constructors will have errored if AbsolutePath doesn't at the
//very least point to a valid location on disk. For example, "/Users/YOURUSERNAME/Code/go/src/github.com/jkomoros/boardgame/examples/memory"
func (p *Pkg) AbsolutePath() string {
	return p.absolutePath
}

//ReadOnly returns true if the package appears to be in a read-only location
//(e.g. a cached module checkout)
func (p *Pkg) ReadOnly() bool {

	absPath := p.AbsolutePath()

	modulePath := filepath.Join(os.Getenv("GOPATH"), "pkg", "mod")

	//TODO: check the file permissions on package files to check

	return strings.Contains(absPath, modulePath)

}

//goPkg validates that the absolutePath denotes a package with at least one go
//file. If there's an error will default to false.
func (g *Pkg) goPkg() bool {

	infos, _ := ioutil.ReadDir(g.AbsolutePath())

	for _, info := range infos {
		if filepath.Ext(info.Name()) == ".go" {
			return true
		}
	}

	return false

}

//Import returns the string that could be used in your source to import this
//package, for exampjle "github.com/jkomoros/boardgame/examples/memory"
func (p *Pkg) Import() (string, error) {
	//Calculate it if not already calculated (for example via NewFromImport constructor)
	if p.importPath == "" {

		goPkg, err := build.ImportDir(p.AbsolutePath(), 0)

		if err != nil {
			return "", errors.New("Couldn't read package: " + err.Error())
		}

		//TODO: factor this into a helper that also sets the package name in
		//case it's asked for later.
		p.importPath = goPkg.ImportPath
	}

	return p.importPath, nil
}

//isPkg verifies that the package appears to be a valid game package.
//Specifically it checks for
func (g *Pkg) isGamePkg() (bool, error) {
	if !g.calculatedIsGamePkg {
		g.memoizedIsGamePkg, g.memoizedIsGamePkgErr = g.calculateIsGamePkg()
	}
	return g.memoizedIsGamePkg, g.memoizedIsGamePkgErr
}

func (g *Pkg) calculateIsGamePkg() (bool, error) {
	pkgs, err := parser.ParseDir(token.NewFileSet(), g.AbsolutePath(), nil, 0)

	if err != nil {
		return false, errors.New("Couldn't parse folder: " + err.Error())
	}

	if len(pkgs) < 1 {
		return false, errors.New("No packages in that directory")
	}

	if len(pkgs) > 1 {
		return false, errors.New("More than one package in that directory")
	}

	var pkg *ast.Package

	for _, p := range pkgs {
		pkg = p
	}

	foundNewDelegate := false

	for _, file := range pkg.Files {
		for _, decl := range file.Decls {
			fun, ok := decl.(*ast.FuncDecl)
			if !ok {
				continue
			}

			if fun.Name.String() != "NewDelegate" {
				continue
			}

			//OK, it might be the function. Does it have the right signature?

			if fun.Recv != nil {
				return false, errors.New("NewDelegate had a receiver")
			}

			if fun.Type.Params.NumFields() > 0 {
				return false, errors.New("NewDelegate took more than 0 items")
			}

			if fun.Type.Results.NumFields() != 1 {
				return false, errors.New("NewDelegate didn't return exactly one item")
			}

			//TODO: check that the returned item implements
			//boardgame.GameDelegate.

			foundNewDelegate = true
			break

		}

		if foundNewDelegate {
			break
		}
	}

	if !foundNewDelegate {
		return false, errors.New("Couldn't find NewDelegate")
	}

	return true, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/mrjones/oauth"
)

type HardCodedSecretGetter map[string]string
func (h HardCodedSecretGetter) secretGetter(key string, header map[string]string) (*oauth.Consumer, error) {
	secret, ok := h[key]
	if !ok {
		return nil, fmt.Errorf("oauth_consumer_key %s is unknown")
	}

	c := oauth.NewConsumer(key, secret, oauth.ServiceProvider{})
	return c, nil
}

func main() {
	var secrets = HardCodedSecretGetter{
		"test": "secret",
	}
	var provider = oauth.NewProvider(secrets.secretGetter)

	http.HandleFunc("/launch", func (w http.ResponseWriter, r *http.Request) {
		authorized, err := provider.IsAuthorized(r)
		if err != nil {
			log.Println(err)
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		if authorized == nil {
			w.WriteHeader(http.StatusUnauthorized)
		}

		w.WriteHeader(http.StatusOK)
		w.Write([]byte("launch authorized"))
	})

	log.Fatal(http.ListenAndServe("0.0.0.0:9999", nil))
}
<commit_msg>use a simple template to render launch params<commit_after>package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"

	"github.com/mrjones/oauth"
)

type HardCodedSecretGetter map[string]string
func (h HardCodedSecretGetter) secretGetter(key string, header map[string]string) (*oauth.Consumer, error) {
	secret, ok := h[key]
	if !ok {
		return nil, fmt.Errorf("oauth_consumer_key %s is unknown")
	}

	c := oauth.NewConsumer(key, secret, oauth.ServiceProvider{})
	return c, nil
}

func main() {
	var secrets = HardCodedSecretGetter{
		"test": "secret",
	}
	var provider = oauth.NewProvider(secrets.secretGetter)
	// TODO: figure out how to bundle template files with go binaries
	var pageTemplate = template.Must(template.New("ltiBootstrap").Parse(pageTemplateString))

	http.HandleFunc("/launch", func (w http.ResponseWriter, r *http.Request) {
		authorized, err := provider.IsAuthorized(r)
		if err != nil {
			log.Println(err)
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		if authorized == nil {
			w.WriteHeader(http.StatusUnauthorized)
		}

		w.WriteHeader(http.StatusOK)
		r.ParseForm()
		pageTemplate.Execute(w, r.Form)
	})

	log.Fatal(http.ListenAndServe("0.0.0.0:9999", nil))
}

const pageTemplateString = `

    <title>Bootstrap LTI</title>

LTI Launch Parameters

          Key
          Values

        {{ range $key, $values := . }}

          {{ $key }}
          {{ $values }}

        {{ end }}

	`
<|endoftext|>