<commit_before>package supergollider

/*
import "testing"

func TestChain(t *testing.T) {
	tr := newTrack(BPM(120), M("1/4")*4)
	// fmt.Println(tr.Tempi[0].Tempo.MilliSecs(M("1/4")))

	tr.At(M("0"), On(v1, note(2)))
	tr.At(M("1/4"), Off(v1))
	tr.Compile()

	if tr.Events[1].Tick != 500000000 {
		t.Errorf("expecting 500000000, got %v", tr.Events[1].Tick)
	}

	tr.SetTempo(M("0"), BPM(240))
	tr.Compile()

	if tr.Events[1].Tick != 250000000 {
		t.Errorf("expecting 250000000, got %v", tr.Events[1].Tick)
	}

}
*/

/*
func TestAtSeq(t *testing.T) {
	tr := NewTrack(BPM(120), M("1/4")*4)

	tr.At(M("0"), On(v1, note(2)))
	tr.At(M("1/4"), Off(v1))
	tr.SetTempo(M("2/4"), BPM(240))
	tr.At(M("2/4"), On(v1, note(2)))
	tr.At(M("3/4"), Off(v1))
	tr.NextBar()
	tr.At(M("0"), On(v1, note(2)))
	tr.At(M("1/4"), Off(v1))

	tr.Compile()

	if tr.Events[0].Tick != 0 {
		t.Errorf("expecting 0, got %v", tr.Events[0].Tick)
	}

	if tr.Events[1].Tick != 500000000 {
		t.Errorf("expecting 500000000, got %v", tr.Events[1].Tick)
	}

	if tr.Events[2].Tick != 1000000000 {
		t.Errorf("expecting 1000000000, got %v", tr.Events[2].Tick)
	}

	if tr.Events[3].Tick != 1250000000 {
		t.Errorf("expecting 1250000000, got %v", tr.Events[3].Tick)
	}

	if tr.Events[4].Tick != 1500000000 {
		t.Errorf("expecting 1500000000, got %v", tr.Events[4].Tick)
	}

	if tr.Events[5].Tick != 1750000000 {
		t.Errorf("expecting 1750000000, got %v", tr.Events[5].Tick)
	}
}

func TestBarChange(t *testing.T) {
	tr := NewTrack(BPM(120), M("4/4"))

	tr.At(M("0"), On(v1, note(2)))
	tr.At(M("1/4"), Off(v1))
	tr.ChangeBar(M("3/4"))
	tr.At(M("1/4"), On(v1, note(2)))
	tr.NextBar()
	tr.At(M("0"), On(v1, note(2)))
	tr.NextBar()
	tr.At(M("0"), Off(v1))

	tr.Compile()

	fac := uint(500000000)

	if tr.Events[0].Tick != 0 {
		t.Errorf("expecting 0, got %v", tr.Events[0].Tick)
	}

	if tr.Events[1].Tick != fac {
		t.Errorf("expecting %d, got %v", fac, tr.Events[1].Tick)
	}

	if tr.Events[2].Tick != fac*4 {
		t.Errorf("expecting %d, got %v", fac*4, tr.Events[2].Tick)
	}

	if tr.Events[3].Tick != fac*6 {
		t.Errorf("expecting %d, got %v", fac*6, tr.Events[3].Tick)
	}

	if tr.Events[4].Tick != fac*9 {
		t.Errorf("expecting %d, got %v", fac*9, tr.Events[4].Tick)
	}
}
*/
<commit_msg>fix chain test<commit_after>package supergollider

import (
	"github.com/metakeule/supergollider/note"

	"testing"
)

func TestChain(t *testing.T) {
	tr := newTrack(BPM(120), M("1/4")*4)
	// fmt.Println(tr.Tempi[0].Tempo.MilliSecs(M("1/4")))

	tr.At(M("0"), OnEvent(nil, note.A2))
	tr.At(M("1/4"), OffEvent(nil))

	tr.compile()

	if tr.Events[1].tick != 500000000 {
		t.Errorf("expecting 500000000, got %v", tr.Events[1].tick)
	}

	tr.SetTempo(M("0"), BPM(240))
	tr.compile()

	if tr.Events[1].tick != 250000000 {
		t.Errorf("expecting 250000000, got %v", tr.Events[1].tick)
	}
}

func TestAtSeq(t *testing.T) {
	var v1 *Voice
	tr := newTrack(BPM(120), M("1/4")*4)
	tr.Start()
	tr.At(M("0"), OnEvent(v1, note.A2))
	tr.At(M("1/4"), OffEvent(v1))
	tr.SetTempo(M("2/4"), BPM(240))
	tr.At(M("2/4"), OnEvent(v1, note.A2))
	tr.At(M("3/4"), OffEvent(v1))
	tr.nextBar()
	tr.At(M("0"), OnEvent(v1, note.A2))
	tr.At(M("1/4"), OffEvent(v1))

	tr.compile()

	if tr.Events[0].tick != 0 {
		t.Errorf("expecting 0, got %v", tr.Events[0].tick)
	}

	if tr.Events[1].tick != 500000000 {
		t.Errorf("expecting 500000000, got %v", tr.Events[1].tick)
	}

	if tr.Events[2].tick != 1000000000 {
		t.Errorf("expecting 1000000000, got %v", tr.Events[2].tick)
	}

	if tr.Events[3].tick != 1250000000 {
		t.Errorf("expecting 1250000000, got %v", tr.Events[3].tick)
	}

	if tr.Events[4].tick != 1500000000 {
		t.Errorf("expecting 1500000000, got %v", tr.Events[4].tick)
	}

	if tr.Events[5].tick != 1750000000 {
		t.Errorf("expecting 1750000000, got %v", tr.Events[5].tick)
	}
}

func TestBarChange(t *testing.T) {
	var v1 *Voice
	tr := newTrack(BPM(120), M("4/4"))
	tr.Start()
	tr.At(M("0"), OnEvent(v1, note.A2))
	tr.At(M("1/4"), OffEvent(v1))
	tr.changeBar(M("3/4"))
	tr.At(M("1/4"), OnEvent(v1, note.A2))
	tr.nextBar()
	tr.At(M("0"), OnEvent(v1, note.A2))
	tr.nextBar()
	tr.At(M("0"), OffEvent(v1))

	tr.compile()

	fac := uint(500000000)

	if tr.Events[0].tick != 0 {
		t.Errorf("expecting 0, got %v", tr.Events[0].tick)
	}

	if tr.Events[1].tick != fac {
		t.Errorf("expecting %d, got %v", fac, tr.Events[1].tick)
	}

	if tr.Events[2].tick != fac*4 {
		t.Errorf("expecting %d, got %v", fac*4, tr.Events[2].tick)
	}

	if tr.Events[3].tick != fac*6 {
		t.Errorf("expecting %d, got %v", fac*6, tr.Events[3].tick)
	}

	if tr.Events[4].tick != fac*9 {
		t.Errorf("expecting %d, got %v", fac*9, tr.Events[4].tick)
	}
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, Mitchell Cooper
package main

import (
	wikiclient "github.com/cooper/go-wikiclient"
	"net/http"
	"regexp"
	"time"
)

var imageRegex = regexp.MustCompile("")

// master handler
func handleRoot(w http.ResponseWriter, r *http.Request) {
	var delayedWiki *wikiInfo

	// try each wiki
	for _, wiki := range wikis {

		// wrong host
		if wiki.host != r.Host {

			// if the wiki host is empty, it is the fallback wiki.
			// delay it until we've checked all other wikis.
			if wiki.host == "" && delayedWiki == nil {
				delayedWiki = &wiki
			}

			continue
		}

		// host matches
		if handleMainPage(wiki, w, r) {
			return
		} else {
			delayedWiki = nil
			break
		}
	}

	// try the delayed wiki
	if delayedWiki != nil {
		if handleMainPage(*delayedWiki, w, r) {
			return
		}
	}

	// anything else is a 404
	http.NotFound(w, r)
}

func handleMainPage(wiki wikiInfo, w http.ResponseWriter, r *http.Request) bool {

	// wrong root
	wikiRoot := wiki.conf.Get("root.wiki")
	if r.URL.Path != wikiRoot && r.URL.Path != wikiRoot+"/" {
		return false
	}

	// main page
	mainPage := wiki.conf.Get("main_page")
	if mainPage != "" {
		wiki.client = wikiclient.NewClient(tr, wiki.defaultSess, 3*time.Second)
		handlePage(wiki, mainPage, w, r)
		return true
	}

	return false
}

// page request
func handlePage(wiki wikiInfo, relPath string, w http.ResponseWriter, r *http.Request) {
	res, err := wiki.client.DisplayPage(relPath)
	if handleError(wiki, err, w, r) || handleError(wiki, res, w, r) {
		return
	}
	renderTemplate(wiki, w, "page", wikiPage{
		Res:        res,
		Title:      res.Get("title"),
		WikiTitle:  wiki.title,
		WikiLogo:   wiki.template.logo,
		WikiRoot:   wiki.conf.Get("root.wiki"),
		StaticRoot: wiki.template.staticRoot,
		navigation: wiki.conf.GetSlice("navigation"),
	})
}

// image request
func handleImage(wiki wikiInfo, relPath string, w http.ResponseWriter, r *http.Request) {
	res, err := wiki.client.DisplayImage(relPath, 0, 0)
	if handleError(wiki, err, w, r) || handleError(wiki, res, w, r) {
		return
	}
	http.ServeFile(w, r, res.Get("path"))
}

// this is set true when calling handlePage for the error page. this way, if an
// error occurs when trying to display the error page, we don't infinitely loop
// between handleError and handlePage
var useLowLevelError bool

func handleError(wiki wikiInfo, errMaybe interface{}, w http.ResponseWriter, r *http.Request) bool {
	msg := "An unknown error has occurred"
	switch err := errMaybe.(type) {

	// if there's no error, stop
	case nil:
		return false

		// message of type "not found" is an error; otherwise, stop
	case wikiclient.Message:
		if err.Get("type") != "not found" {
			return false
		}
		msg = err.Get("error")

		// string
	case string:
		msg = err

		// error
	case error:
		msg = err.Error()

	}

	// if we have an error page, use it
	errorPage := wiki.conf.Get("error_page")
	if !useLowLevelError && errorPage != "" {
		useLowLevelError = true
		handlePage(wiki, errorPage, w, r)
		useLowLevelError = false
		return true
	}

	// generic error response
	http.Error(w, msg, http.StatusNotFound)
	return true
}

func renderTemplate(wiki wikiInfo, w http.ResponseWriter, templateName string, p wikiPage) {
	err := wiki.template.template.ExecuteTemplate(w, templateName+".tpl", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
<commit_msg>don't break<commit_after>// Copyright (c) 2017, Mitchell Cooper
package main

import (
	wikiclient "github.com/cooper/go-wikiclient"
	"net/http"
	"regexp"
	"time"
)

var imageRegex = regexp.MustCompile("")

// master handler
func handleRoot(w http.ResponseWriter, r *http.Request) {
	var delayedWiki *wikiInfo

	// try each wiki
	for _, wiki := range wikis {

		// wrong host
		if wiki.host != r.Host {

			// if the wiki host is empty, it is the fallback wiki.
			// delay it until we've checked all other wikis.
			if wiki.host == "" && delayedWiki == nil {
				delayedWiki = &wiki
			}

			continue
		}

		// host matches
		if handleMainPage(wiki, w, r) {
			return
		}
	}

	// try the delayed wiki
	if delayedWiki != nil {
		if handleMainPage(*delayedWiki, w, r) {
			return
		}
	}

	// anything else is a 404
	http.NotFound(w, r)
}

func handleMainPage(wiki wikiInfo, w http.ResponseWriter, r *http.Request) bool {

	// wrong root
	wikiRoot := wiki.conf.Get("root.wiki")
	if r.URL.Path != wikiRoot && r.URL.Path != wikiRoot+"/" {
		return false
	}

	// no main page configured
	mainPage := wiki.conf.Get("main_page")
	if mainPage == "" {
		return false
	}

	wiki.client = wikiclient.NewClient(tr, wiki.defaultSess, 3*time.Second)
	handlePage(wiki, mainPage, w, r)
	return true
}

// page request
func handlePage(wiki wikiInfo, relPath string, w http.ResponseWriter, r *http.Request) {
	res, err := wiki.client.DisplayPage(relPath)
	if handleError(wiki, err, w, r) || handleError(wiki, res, w, r) {
		return
	}
	renderTemplate(wiki, w, "page", wikiPage{
		Res:        res,
		Title:      res.Get("title"),
		WikiTitle:  wiki.title,
		WikiLogo:   wiki.template.logo,
		WikiRoot:   wiki.conf.Get("root.wiki"),
		StaticRoot: wiki.template.staticRoot,
		navigation: wiki.conf.GetSlice("navigation"),
	})
}

// image request
func handleImage(wiki wikiInfo, relPath string, w http.ResponseWriter, r *http.Request) {
	res, err := wiki.client.DisplayImage(relPath, 0, 0)
	if handleError(wiki, err, w, r) || handleError(wiki, res, w, r) {
		return
	}
	http.ServeFile(w, r, res.Get("path"))
}

// this is set true when calling handlePage for the error page. this way, if an
// error occurs when trying to display the error page, we don't infinitely loop
// between handleError and handlePage
var useLowLevelError bool

func handleError(wiki wikiInfo, errMaybe interface{}, w http.ResponseWriter, r *http.Request) bool {
	msg := "An unknown error has occurred"
	switch err := errMaybe.(type) {

	// if there's no error, stop
	case nil:
		return false

		// message of type "not found" is an error; otherwise, stop
	case wikiclient.Message:
		if err.Get("type") != "not found" {
			return false
		}
		msg = err.Get("error")

		// string
	case string:
		msg = err

		// error
	case error:
		msg = err.Error()

	}

	// if we have an error page, use it
	errorPage := wiki.conf.Get("error_page")
	if !useLowLevelError && errorPage != "" {
		useLowLevelError = true
		handlePage(wiki, errorPage, w, r)
		useLowLevelError = false
		return true
	}

	// generic error response
	http.Error(w, msg, http.StatusNotFound)
	return true
}

func renderTemplate(wiki wikiInfo, w http.ResponseWriter, templateName string, p wikiPage) {
	err := wiki.template.template.ExecuteTemplate(w, templateName+".tpl", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}
<|endoftext|>


<commit_before><commit_msg>Add debugging command to dump all command-line arguments.<commit_after><|endoftext|>


<commit_before>// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
//
// 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 table

import (
	"fmt"

	"github.com/osrg/gobgp/packet/bgp"
)

type AdjRib struct {
	accepted map[bgp.RouteFamily]int
	table    map[bgp.RouteFamily]map[string]*Path
}

func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib {
	table := make(map[bgp.RouteFamily]map[string]*Path)
	for _, rf := range rfList {
		table[rf] = make(map[string]*Path)
	}
	return &AdjRib{
		table:    table,
		accepted: make(map[bgp.RouteFamily]int),
	}
}

func (adj *AdjRib) Update(pathList []*Path) {
	for _, path := range pathList {
		if path == nil || path.IsEOR() {
			continue
		}
		rf := path.GetRouteFamily()
		key := fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.getPrefix())

		old, found := adj.table[rf][key]
		if path.IsWithdraw {
			if found {
				delete(adj.table[rf], key)
				adj.accepted[rf]--
			}
		} else {
			if found {
			} else {
				adj.accepted[rf]++
			}
			if found && old.Equal(path) {
				path.setTimestamp(old.GetTimestamp())
			}
			adj.table[rf][key] = path
		}
	}
}

func (adj *AdjRib) RefreshAcceptedNumber(rfList []bgp.RouteFamily) {
	for _, rf := range rfList {
		adj.accepted[rf] = len(adj.table[rf])
	}
}

func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
	pathList := make([]*Path, 0, adj.Count(rfList))
	for _, rf := range rfList {
		for _, rr := range adj.table[rf] {
			pathList = append(pathList, rr)
		}
	}
	return pathList
}

func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int {
	count := 0
	for _, rf := range rfList {
		if table, ok := adj.table[rf]; ok {
			count += len(table)
		}
	}
	return count
}

func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int {
	count := 0
	for _, rf := range rfList {
		if n, ok := adj.accepted[rf]; ok {
			count += n
		}
	}
	return count
}

func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) {
	for _, rf := range rfList {
		if _, ok := adj.table[rf]; ok {
			adj.table[rf] = make(map[string]*Path)
			adj.accepted[rf] = 0
		}
	}
}

func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path {
	pathList := make([]*Path, 0, adj.Count(rfList))
	for _, rf := range rfList {
		if table, ok := adj.table[rf]; ok {
			for _, p := range table {
				if p.IsStale() {
					delete(table, p.getPrefix())
					adj.accepted[rf]--
					pathList = append(pathList, p.Clone(true))
				}
			}
		}
	}
	return pathList
}

func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path {
	pathList := make([]*Path, 0)
	for _, rf := range rfList {
		if table, ok := adj.table[rf]; ok {
			l := make([]*Path, 0, len(table))
			for k, p := range table {
				n := p.Clone(false)
				n.MarkStale(true)
				table[k] = n
				l = append(l, n)
			}
			if len(l) > 0 {
				pathList = append(pathList, l...)
			}
		}
	}
	return pathList
}

func (adj *AdjRib) Exists(path *Path) bool {
	if path == nil {
		return false
	}
	family := path.GetRouteFamily()
	table, ok := adj.table[family]
	if !ok {
		return false
	}
	_, ok = table[path.getPrefix()]
	return ok
}

func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) {
	m := make(map[string][]*Path)
	pl := adj.PathList([]bgp.RouteFamily{family}, accepted)
	for _, path := range pl {
		key := path.GetNlri().String()
		if _, y := m[key]; y {
			m[key] = append(m[key], path)
		} else {
			m[key] = []*Path{path}
		}
	}
	d := make([]*Destination, 0, len(pl))
	for _, l := range m {
		d = append(d, NewDestination(l[0].GetNlri(), 0, l...))
	}
	tbl := NewTable(family, d...)
	option = append(option, TableSelectOption{adj: true})
	return tbl.Select(option...)
}

func (adj *AdjRib) TableInfo(family bgp.RouteFamily) (*TableInfo, error) {
	if _, ok := adj.table[family]; !ok {
		return nil, fmt.Errorf("%s unsupported", family)
	}
	c := adj.Count([]bgp.RouteFamily{family})
	a := adj.Accepted([]bgp.RouteFamily{family})
	return &TableInfo{
		NumDestination: c,
		NumPath:        c,
		NumAccepted:    a,
	}, nil
}
<commit_msg>table: remove unused Exists method in AdjRib strcture<commit_after>// Copyright (C) 2015 Nippon Telegraph and Telephone Corporation.
//
// 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 table

import (
	"fmt"

	"github.com/osrg/gobgp/packet/bgp"
)

type AdjRib struct {
	accepted map[bgp.RouteFamily]int
	table    map[bgp.RouteFamily]map[string]*Path
}

func NewAdjRib(rfList []bgp.RouteFamily) *AdjRib {
	table := make(map[bgp.RouteFamily]map[string]*Path)
	for _, rf := range rfList {
		table[rf] = make(map[string]*Path)
	}
	return &AdjRib{
		table:    table,
		accepted: make(map[bgp.RouteFamily]int),
	}
}

func (adj *AdjRib) Update(pathList []*Path) {
	for _, path := range pathList {
		if path == nil || path.IsEOR() {
			continue
		}
		rf := path.GetRouteFamily()
		key := fmt.Sprintf("%d:%s", path.GetNlri().PathIdentifier(), path.getPrefix())

		old, found := adj.table[rf][key]
		if path.IsWithdraw {
			if found {
				delete(adj.table[rf], key)
				adj.accepted[rf]--
			}
		} else {
			if found {
			} else {
				adj.accepted[rf]++
			}
			if found && old.Equal(path) {
				path.setTimestamp(old.GetTimestamp())
			}
			adj.table[rf][key] = path
		}
	}
}

func (adj *AdjRib) RefreshAcceptedNumber(rfList []bgp.RouteFamily) {
	for _, rf := range rfList {
		adj.accepted[rf] = len(adj.table[rf])
	}
}

func (adj *AdjRib) PathList(rfList []bgp.RouteFamily, accepted bool) []*Path {
	pathList := make([]*Path, 0, adj.Count(rfList))
	for _, rf := range rfList {
		for _, rr := range adj.table[rf] {
			pathList = append(pathList, rr)
		}
	}
	return pathList
}

func (adj *AdjRib) Count(rfList []bgp.RouteFamily) int {
	count := 0
	for _, rf := range rfList {
		if table, ok := adj.table[rf]; ok {
			count += len(table)
		}
	}
	return count
}

func (adj *AdjRib) Accepted(rfList []bgp.RouteFamily) int {
	count := 0
	for _, rf := range rfList {
		if n, ok := adj.accepted[rf]; ok {
			count += n
		}
	}
	return count
}

func (adj *AdjRib) Drop(rfList []bgp.RouteFamily) {
	for _, rf := range rfList {
		if _, ok := adj.table[rf]; ok {
			adj.table[rf] = make(map[string]*Path)
			adj.accepted[rf] = 0
		}
	}
}

func (adj *AdjRib) DropStale(rfList []bgp.RouteFamily) []*Path {
	pathList := make([]*Path, 0, adj.Count(rfList))
	for _, rf := range rfList {
		if table, ok := adj.table[rf]; ok {
			for _, p := range table {
				if p.IsStale() {
					delete(table, p.getPrefix())
					adj.accepted[rf]--
					pathList = append(pathList, p.Clone(true))
				}
			}
		}
	}
	return pathList
}

func (adj *AdjRib) StaleAll(rfList []bgp.RouteFamily) []*Path {
	pathList := make([]*Path, 0)
	for _, rf := range rfList {
		if table, ok := adj.table[rf]; ok {
			l := make([]*Path, 0, len(table))
			for k, p := range table {
				n := p.Clone(false)
				n.MarkStale(true)
				table[k] = n
				l = append(l, n)
			}
			if len(l) > 0 {
				pathList = append(pathList, l...)
			}
		}
	}
	return pathList
}

func (adj *AdjRib) Select(family bgp.RouteFamily, accepted bool, option ...TableSelectOption) (*Table, error) {
	m := make(map[string][]*Path)
	pl := adj.PathList([]bgp.RouteFamily{family}, accepted)
	for _, path := range pl {
		key := path.GetNlri().String()
		if _, y := m[key]; y {
			m[key] = append(m[key], path)
		} else {
			m[key] = []*Path{path}
		}
	}
	d := make([]*Destination, 0, len(pl))
	for _, l := range m {
		d = append(d, NewDestination(l[0].GetNlri(), 0, l...))
	}
	tbl := NewTable(family, d...)
	option = append(option, TableSelectOption{adj: true})
	return tbl.Select(option...)
}

func (adj *AdjRib) TableInfo(family bgp.RouteFamily) (*TableInfo, error) {
	if _, ok := adj.table[family]; !ok {
		return nil, fmt.Errorf("%s unsupported", family)
	}
	c := adj.Count([]bgp.RouteFamily{family})
	a := adj.Accepted([]bgp.RouteFamily{family})
	return &TableInfo{
		NumDestination: c,
		NumPath:        c,
		NumAccepted:    a,
	}, nil
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gophergala2016/goad"
	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/gorilla/websocket"
	"github.com/gophergala2016/goad/queue"
)

var addr = flag.String("addr", ":8080", "http service address")
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func main() {
	Serve()
}

func jsonFromRegionsAggData(result queue.RegionsAggData) (string, error) {
	data, jsonerr := json.Marshal(result)
	if jsonerr != nil {
		return "", jsonerr
	}
	return string(data), nil
}

func serveResults(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/goad" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	url := r.URL.Query().Get("url")
	if len(url) == 0 {
		http.Error(w, "Missing URL", 400)
		return
	}

	concurrencyStr := r.URL.Query().Get("c")
	concurrency, cerr := strconv.Atoi(concurrencyStr)
	if cerr != nil {
		http.Error(w, "Invalid concurrency", 400)
		return
	}

	totStr := r.URL.Query().Get("tot")
	tot, toterr := strconv.Atoi(totStr)
	if toterr != nil {
		http.Error(w, "Invalid total", 400)
		return
	}

	timeoutStr := r.URL.Query().Get("timeout")
	timeout, timeouterr := strconv.Atoi(timeoutStr)
	if timeouterr != nil {
		http.Error(w, "Invalid timeout", 400)
		return
	}

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Websocket upgrade:", err)
		return
	}
	defer c.Close()

	config := goad.TestConfig{
		url,
		uint(concurrency),
		uint(tot),
		time.Duration(timeout),
		"eu-west-1",
	}

	test, testerr := goad.NewTest(&config)
	if testerr != nil {
		fmt.Println(testerr)
		return
	}
	resultChan := test.Start()

	for result := range resultChan {
		message, jsonerr := jsonFromRegionsAggData(result)
		if jsonerr != nil {
			log.Println(jsonerr)
			break
		}
		go readLoop(c)
		err = c.WriteMessage(websocket.TextMessage, []byte(message))
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func readLoop(c *websocket.Conn) {
	for {
		if _, _, err := c.NextReader(); err != nil {
			c.Close()
			break
		}
	}
}

func health(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Serve waits for connections and serves the results
func Serve() {
	http.HandleFunc("/goad", serveResults)
	http.HandleFunc("/_health", health)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Hard code web limits<commit_after>package main

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

	"github.com/gophergala2016/goad"
	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/gorilla/websocket"
	"github.com/gophergala2016/goad/queue"
)

var addr = flag.String("addr", ":8080", "http service address")
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func main() {
	Serve()
}

func jsonFromRegionsAggData(result queue.RegionsAggData) (string, error) {
	data, jsonerr := json.Marshal(result)
	if jsonerr != nil {
		return "", jsonerr
	}
	return string(data), nil
}

func serveResults(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/goad" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	url := r.URL.Query().Get("url")
	if len(url) == 0 {
		http.Error(w, "Missing URL", 400)
		return
	}

	// Commented out param handling, we have hard coded limits for the website testing
	//
	// concurrencyStr := r.URL.Query().Get("c")
	// concurrency, cerr := strconv.Atoi(concurrencyStr)
	// if cerr != nil {
	// 	http.Error(w, "Invalid concurrency", 400)
	// 	return
	// }
	//
	// totStr := r.URL.Query().Get("tot")
	// tot, toterr := strconv.Atoi(totStr)
	// if toterr != nil {
	// 	http.Error(w, "Invalid total", 400)
	// 	return
	// }
	//
	// timeoutStr := r.URL.Query().Get("timeout")
	// timeout, timeouterr := strconv.Atoi(timeoutStr)
	// if timeouterr != nil {
	// 	http.Error(w, "Invalid timeout", 400)
	// 	return
	// }

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Websocket upgrade:", err)
		return
	}
	defer c.Close()

	config := goad.TestConfig{
		url,
		5,
		1000,
		time.Duration(7),
		"eu-west-1",
	}

	test, testerr := goad.NewTest(&config)
	if testerr != nil {
		fmt.Println(testerr)
		return
	}
	resultChan := test.Start()

	for result := range resultChan {
		message, jsonerr := jsonFromRegionsAggData(result)
		if jsonerr != nil {
			log.Println(jsonerr)
			break
		}
		go readLoop(c)
		err = c.WriteMessage(websocket.TextMessage, []byte(message))
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func readLoop(c *websocket.Conn) {
	for {
		if _, _, err := c.NextReader(); err != nil {
			c.Close()
			break
		}
	}
}

func health(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Serve waits for connections and serves the results
func Serve() {
	http.HandleFunc("/goad", serveResults)
	http.HandleFunc("/_health", health)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gophergala2016/goad"
	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/gorilla/websocket"
	"github.com/gophergala2016/goad/queue"
)

var addr = flag.String("addr", ":8080", "http service address")
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func main() {
	Serve()
}

func jsonFromRegionsAggData(result queue.RegionsAggData) (string, error) {
	data, jsonerr := json.Marshal(result)
	if jsonerr != nil {
		return "", jsonerr
	}
	return string(data), nil
}

func serveResults(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/goad" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	url := r.URL.Query().Get("url")
	if len(url) == 0 {
		http.Error(w, "Missing URL", 400)
		return
	}

	// Commented out param handling, we have hard coded limits for the website testing
	//
	// concurrencyStr := r.URL.Query().Get("c")
	// concurrency, cerr := strconv.Atoi(concurrencyStr)
	// if cerr != nil {
	// 	http.Error(w, "Invalid concurrency", 400)
	// 	return
	// }
	//
	// totStr := r.URL.Query().Get("tot")
	// tot, toterr := strconv.Atoi(totStr)
	// if toterr != nil {
	// 	http.Error(w, "Invalid total", 400)
	// 	return
	// }
	//
	// timeoutStr := r.URL.Query().Get("timeout")
	// timeout, timeouterr := strconv.Atoi(timeoutStr)
	// if timeouterr != nil {
	// 	http.Error(w, "Invalid timeout", 400)
	// 	return
	// }

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Websocket upgrade:", err)
		return
	}
	defer c.Close()

	config := goad.TestConfig{
		URL:            url,
		Concurrency:    5,
		TotalRequests:  1000,
		RequestTimeout: time.Duration(7),
		Regions:        []string{"us-east-1"},
	}

	test, testerr := goad.NewTest(&config)
	if testerr != nil {
		fmt.Println(testerr)
		return
	}
	resultChan := test.Start()

	for result := range resultChan {
		message, jsonerr := jsonFromRegionsAggData(result)
		if jsonerr != nil {
			log.Println(jsonerr)
			break
		}
		go readLoop(c)
		err = c.WriteMessage(websocket.TextMessage, []byte(message))
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func readLoop(c *websocket.Conn) {
	for {
		if _, _, err := c.NextReader(); err != nil {
			c.Close()
			break
		}
	}
}

func health(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Serve waits for connections and serves the results
func Serve() {
	http.HandleFunc("/goad", serveResults)
	http.HandleFunc("/_health", health)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>7 nanoseconds is just too small of a timeout<commit_after>package main

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

	"github.com/gophergala2016/goad"
	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/gorilla/websocket"
	"github.com/gophergala2016/goad/queue"
)

var addr = flag.String("addr", ":8080", "http service address")
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func main() {
	Serve()
}

func jsonFromRegionsAggData(result queue.RegionsAggData) (string, error) {
	data, jsonerr := json.Marshal(result)
	if jsonerr != nil {
		return "", jsonerr
	}
	return string(data), nil
}

func serveResults(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/goad" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	url := r.URL.Query().Get("url")
	if len(url) == 0 {
		http.Error(w, "Missing URL", 400)
		return
	}

	// Commented out param handling, we have hard coded limits for the website testing
	//
	// concurrencyStr := r.URL.Query().Get("c")
	// concurrency, cerr := strconv.Atoi(concurrencyStr)
	// if cerr != nil {
	// 	http.Error(w, "Invalid concurrency", 400)
	// 	return
	// }
	//
	// totStr := r.URL.Query().Get("tot")
	// tot, toterr := strconv.Atoi(totStr)
	// if toterr != nil {
	// 	http.Error(w, "Invalid total", 400)
	// 	return
	// }
	//
	// timeoutStr := r.URL.Query().Get("timeout")
	// timeout, timeouterr := strconv.Atoi(timeoutStr)
	// if timeouterr != nil {
	// 	http.Error(w, "Invalid timeout", 400)
	// 	return
	// }

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Websocket upgrade:", err)
		return
	}
	defer c.Close()

	config := goad.TestConfig{
		URL:            url,
		Concurrency:    5,
		TotalRequests:  1000,
		RequestTimeout: time.Duration(5 * time.Second),
		Regions:        []string{"us-east-1"},
	}

	test, testerr := goad.NewTest(&config)
	if testerr != nil {
		fmt.Println(testerr)
		return
	}
	resultChan := test.Start()

	for result := range resultChan {
		message, jsonerr := jsonFromRegionsAggData(result)
		if jsonerr != nil {
			log.Println(jsonerr)
			break
		}
		go readLoop(c)
		err = c.WriteMessage(websocket.TextMessage, []byte(message))
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func readLoop(c *websocket.Conn) {
	for {
		if _, _, err := c.NextReader(); err != nil {
			c.Close()
			break
		}
	}
}

func health(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Serve waits for connections and serves the results
func Serve() {
	http.HandleFunc("/goad", serveResults)
	http.HandleFunc("/_health", health)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gophergala2016/goad"
	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/gorilla/websocket"
	"github.com/gophergala2016/goad/queue"
)

var addr = flag.String("addr", ":8080", "http service address")
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func main() {
	Serve()
}

func jsonFromRegionsAggData(result queue.RegionsAggData) (string, error) {
	data, jsonerr := json.Marshal(result)
	if jsonerr != nil {
		return "", jsonerr
	}
	return string(data), nil
}

func serveResults(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/goad" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	url := r.URL.Query().Get("url")
	if len(url) == 0 {
		http.Error(w, "Missing URL", 400)
		return
	}

	// Commented out param handling, we have hard coded limits for the website testing
	//
	// concurrencyStr := r.URL.Query().Get("c")
	// concurrency, cerr := strconv.Atoi(concurrencyStr)
	// if cerr != nil {
	// 	http.Error(w, "Invalid concurrency", 400)
	// 	return
	// }
	//
	// totStr := r.URL.Query().Get("tot")
	// tot, toterr := strconv.Atoi(totStr)
	// if toterr != nil {
	// 	http.Error(w, "Invalid total", 400)
	// 	return
	// }
	//
	// timeoutStr := r.URL.Query().Get("timeout")
	// timeout, timeouterr := strconv.Atoi(timeoutStr)
	// if timeouterr != nil {
	// 	http.Error(w, "Invalid timeout", 400)
	// 	return
	// }

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Websocket upgrade:", err)
		return
	}
	defer c.Close()

	config := goad.TestConfig{
		url,
		5,
		1000,
		time.Duration(7),
		"eu-west-1",
	}

	test, testerr := goad.NewTest(&config)
	if testerr != nil {
		fmt.Println(testerr)
		return
	}
	resultChan := test.Start()

	for result := range resultChan {
		message, jsonerr := jsonFromRegionsAggData(result)
		if jsonerr != nil {
			log.Println(jsonerr)
			break
		}
		go readLoop(c)
		err = c.WriteMessage(websocket.TextMessage, []byte(message))
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func readLoop(c *websocket.Conn) {
	for {
		if _, _, err := c.NextReader(); err != nil {
			c.Close()
			break
		}
	}
}

func health(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Serve waits for connections and serves the results
func Serve() {
	http.HandleFunc("/goad", serveResults)
	http.HandleFunc("/_health", health)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<commit_msg>Change web API region to us-east-1<commit_after>package main

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

	"github.com/gophergala2016/goad"
	"github.com/gophergala2016/goad/Godeps/_workspace/src/github.com/gorilla/websocket"
	"github.com/gophergala2016/goad/queue"
)

var addr = flag.String("addr", ":8080", "http service address")
var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func main() {
	Serve()
}

func jsonFromRegionsAggData(result queue.RegionsAggData) (string, error) {
	data, jsonerr := json.Marshal(result)
	if jsonerr != nil {
		return "", jsonerr
	}
	return string(data), nil
}

func serveResults(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/goad" {
		http.Error(w, "Not found", 404)
		return
	}
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")

	url := r.URL.Query().Get("url")
	if len(url) == 0 {
		http.Error(w, "Missing URL", 400)
		return
	}

	// Commented out param handling, we have hard coded limits for the website testing
	//
	// concurrencyStr := r.URL.Query().Get("c")
	// concurrency, cerr := strconv.Atoi(concurrencyStr)
	// if cerr != nil {
	// 	http.Error(w, "Invalid concurrency", 400)
	// 	return
	// }
	//
	// totStr := r.URL.Query().Get("tot")
	// tot, toterr := strconv.Atoi(totStr)
	// if toterr != nil {
	// 	http.Error(w, "Invalid total", 400)
	// 	return
	// }
	//
	// timeoutStr := r.URL.Query().Get("timeout")
	// timeout, timeouterr := strconv.Atoi(timeoutStr)
	// if timeouterr != nil {
	// 	http.Error(w, "Invalid timeout", 400)
	// 	return
	// }

	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("Websocket upgrade:", err)
		return
	}
	defer c.Close()

	config := goad.TestConfig{
		url,
		5,
		1000,
		time.Duration(7),
		"us-east-1",
	}

	test, testerr := goad.NewTest(&config)
	if testerr != nil {
		fmt.Println(testerr)
		return
	}
	resultChan := test.Start()

	for result := range resultChan {
		message, jsonerr := jsonFromRegionsAggData(result)
		if jsonerr != nil {
			log.Println(jsonerr)
			break
		}
		go readLoop(c)
		err = c.WriteMessage(websocket.TextMessage, []byte(message))
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func readLoop(c *websocket.Conn) {
	for {
		if _, _, err := c.NextReader(); err != nil {
			c.Close()
			break
		}
	}
}

func health(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
}

// Serve waits for connections and serves the results
func Serve() {
	http.HandleFunc("/goad", serveResults)
	http.HandleFunc("/_health", health)
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}
<|endoftext|>


<commit_before>package main

/*
    TODO:
    o oop
    o log
    o cmd helper
*/

import (
    "bytes"
    "fmt"
    "io"
    "log"
    "net"
    "os"
    "os/exec"
    "strings"
)

type Config struct {
    Bind string
    Port string
    Cmd string
    CmdArgs []string
}

func main() {
    conf := Config{
        Bind: "127.0.0.1",
        Port: "3000",
        Cmd: "tr",
        CmdArgs: []string{"[::lower:]", "[:upper:]"},
    }
    debug(fmt.Sprintf("Config: %s", conf))

    // listen to a port for a tcp connection
    listener := get_listener(conf)
    run(conf, listener)
}

func get_listener(conf Config) net.Listener {
    addr := conf.Bind + ":" + conf.Port
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        log.Fatal(fmt.Sprintf("Unable to listen to address: [%v] ERROR: %v", addr, err))
    }
    debug(fmt.Sprintf("Listenning to: %v", ln.Addr()))
    return ln
}

func run(conf Config, listener net.Listener) {
    for {
        conn, err := listener.Accept()
        if err != nil {
            errr(fmt.Sprintf("Something went wrong while connecting! ERROR: %v", err))
        } else {
            go handle_conn(conn, conf)
        }
    }
}

func get_cmd(conf Config) *exec.Cmd {
    cmd := exec.Command(conf.Cmd)
    for _, arg := range conf.CmdArgs {
        cmd.Args = append(cmd.Args, arg)
    }
    debug(fmt.Sprintf("cmd: %s", cmd.Args))
    return cmd
}

func handle_conn(conn net.Conn, conf Config) {
    defer conn.Close()

    cmd := get_cmd(conf)
    remote := conn.RemoteAddr()
    from := fmt.Sprintf("%s ", remote)
    debug(fmt.Sprintf("Accepted connection from: %v", remote))

    var buff bytes.Buffer;
    arr := make([]byte, 50)
    prev := make([]byte, 50)
    for {
        prev = arr
        n, err := conn.Read(arr)
        if n > 0 {
            debug(from + fmt.Sprintf("-> Read bytes: %v", n))
            debug(from + fmt.Sprintf("-> data: [%s]", arr[:n]))

            if prev[0] == '\r' && arr[0] == '\r' {
                str := string(buff.Bytes())
                run_cmd(cmd, conn, str)
                debug(from + "XX ... connection closed")
                return
            }

            buff.Write(arr[:n])
        }

        if err != nil {
            if err == io.EOF {
                debug(from + "XX ... connection closed")
                return
            }
            errr(from + fmt.Sprintf("!! Something happened while reading! ERROR: [%v]", err))
            return
        }
    }
}

func run_cmd(cmd *exec.Cmd, conn net.Conn, str string) {
    from := fmt.Sprintf("%s ", conn.RemoteAddr())
    debug(fmt.Sprintf("echo '%s' |", str))

    cmd.Stdin = strings.NewReader(str)
    cmd.Stdout = conn
    cmd.Stderr = conn

    err := cmd.Run()
    if err != nil {
        errr(from + fmt.Sprintf("!! Failed to exec! ERROR: %s\n",  err))
        errstr := strings.NewReader(fmt.Sprintf("err: %s\n", err))
        io.Copy(conn, errstr)
        return
    }

    debug(from + "!! ... Ran cmd")
    debug(fmt.Sprintf("%s", cmd.ProcessState))
}

func debug(log interface{}) {
    fmt.Fprintf(os.Stderr, "[debug] %s\n", log)
}

func errr(log interface{}) {
    fmt.Fprintf(os.Stderr, "[error] %s\n", log)
}
<commit_msg>Add cmd line parse using flag<commit_after>package main

/*
    TODO:
    o oop
    o log
    o chunk i/o
    o keep alive
*/

import (
    "bytes"
    "flag"
    "fmt"
    "io"
    "log"
    "net"
    "os"
    "os/exec"
    "strings"
)

type Config struct {
    Bind string
    Port string
    Cmd string
    CmdArgs []string
}

type Option struct {
    Addr string
    Cmd string
}

var DEBUG bool
var opt Option

func init() {
    const (
        verbose_usage = "Enable verbose"
        verbose_default_val = false
    )

    flag.BoolVar(&DEBUG, "v", verbose_default_val, verbose_usage)
    flag.BoolVar(&DEBUG, "verbose", verbose_default_val, verbose_usage)

    flag.StringVar(&opt.Addr, "addr", "127.0.0.1:3131", "Ip address to bind")
    flag.StringVar(&opt.Cmd, "cmd", "", "Command to run")
}

func main() {
    flag.Parse()
    debug(opt)

    conf := get_conf()
    listener := get_listener(conf)
    run(conf, listener)
}

func get_conf() Config {
    conf := Config{
        Bind: "127.0.0.1",
        Port: "3000",
        Cmd: "",
        CmdArgs: []string{},
    }

    if len(opt.Addr)>0 {
        conf.Bind, conf.Port = parse_opt_addr(opt.Addr)
    }

    conf.Cmd, conf.CmdArgs = parse_opt_cmd(opt.Cmd)

    debug(fmt.Sprintf("Config: %s", conf))
    return conf
}

func parse_opt_addr(addr string) (string, string) {
    addrs := strings.Split(addr, ":")
    if len(addrs) != 2 {
        print_usage()
        log.Fatal("Unable to parse addr")
    }
    return addrs[0], addrs[1]
}

func parse_opt_cmd(cmd string) (string, []string) {
    cmds := strings.Split(cmd, " ")
    if len(cmd) == 0 || len(cmds) < 1 {
        print_usage()
        log.Fatal("Unable to parse cmd. cmd is required.")
    }

    args := make([]string, 0)
    for _, arg := range cmds[1:] {
        if arg == "" || arg == " " { continue; }
        args = append(args, arg)
    }

    return cmds[0], args
}

func print_usage() {
    fmt.Println("Usage: tcpserver [--addr 0.0.0.0:3000] --cmd 'tr a-z A-Z'")
    flag.PrintDefaults()
    fmt.Println()
}

func get_listener(conf Config) net.Listener {
    addr := conf.Bind + ":" + conf.Port
    ln, err := net.Listen("tcp", addr)
    if err != nil {
        log.Fatal(fmt.Sprintf("Unable to listen to address: [%v] ERROR: %v", addr, err))
    }
    debug(fmt.Sprintf("Listenning to: %v", ln.Addr()))
    return ln
}

func run(conf Config, listener net.Listener) {
    for {
        conn, err := listener.Accept()
        if err != nil {
            errr(fmt.Sprintf("Something went wrong while connecting! ERROR: %v", err))
        } else {
            go handle_conn(conn, conf)
        }
    }
}

func get_cmd(conf Config) *exec.Cmd {
    cmd := exec.Command(conf.Cmd)
    for _, arg := range conf.CmdArgs {
        cmd.Args = append(cmd.Args, arg)
    }
    debug(fmt.Sprintf("cmd: %s", cmd.Args))
    return cmd
}

func handle_conn(conn net.Conn, conf Config) {
    defer conn.Close()

    cmd := get_cmd(conf)
    remote := conn.RemoteAddr()
    from := fmt.Sprintf("%s ", remote)
    debug(fmt.Sprintf("Accepted connection from: %v", remote))

    var buff bytes.Buffer;
    arr := make([]byte, 50)
    prev := make([]byte, 50)
    for {
        prev = arr
        n, err := conn.Read(arr)
        if n > 0 {
            debug(from + fmt.Sprintf("-> Read bytes: %v", n))
            debug(from + fmt.Sprintf("-> data: [%s]", arr[:n]))

            if prev[0] == '\r' && arr[0] == '\r' {
                str := string(buff.Bytes())
                run_cmd(cmd, conn, str)
                debug(from + "XX ... connection closed")
                return
            }

            buff.Write(arr[:n])
        }

        if err != nil {
            if err == io.EOF {
                debug(from + "XX ... connection closed")
                return
            }
            errr(from + fmt.Sprintf("!! Something happened while reading! ERROR: [%v]", err))
            return
        }
    }
}

func run_cmd(cmd *exec.Cmd, conn net.Conn, str string) {
    from := fmt.Sprintf("%s ", conn.RemoteAddr())
    debug(fmt.Sprintf("echo '%s' | %s", str, opt.Cmd))

    cmd.Stdin = strings.NewReader(str)
    cmd.Stdout = conn
    cmd.Stderr = conn

    err := cmd.Run()
    if err != nil {
        errr(from + fmt.Sprintf("!! Failed to exec! ERROR: %s\n",  err))
        errstr := strings.NewReader(fmt.Sprintf("err: %s\n", err))
        io.Copy(conn, errstr)
        return
    }

    debug(from + "!! ... Ran cmd")
    debug(fmt.Sprintf("%s", cmd.ProcessState))
}

func debug(log interface{}) {
    if !DEBUG { return; }
    fmt.Fprintf(os.Stderr, "[debug] %s\n", log)
}

func errr(log interface{}) {
    fmt.Fprintf(os.Stderr, "[error] %s\n", log)
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package image

// Color can convert itself to alpha-premultiplied RGBA, with a possible loss
// of precision. Each value ranges within [0, 0xFFFF], but is represented by a
// uint32 so that multiplying by a blend factor up to 0xFFFF will not overflow.
type Color interface {
	RGBA() (r, g, b, a uint32)
}

// RGBAColor represents a traditional 32-bit alpha-premultiplied color,
// having 8 bits for each of red, green, blue and alpha.
type RGBAColor struct {
	R, G, B, A uint8
}

func (c RGBAColor) RGBA() (r, g, b, a uint32) {
	r = uint32(c.R)
	r |= r << 8
	g = uint32(c.G)
	g |= g << 8
	b = uint32(c.B)
	b |= b << 8
	a = uint32(c.A)
	a |= a << 8
	return
}

// RGBA64Color represents a 64-bit alpha-premultiplied color,
// having 16 bits for each of red, green, blue and alpha.
type RGBA64Color struct {
	R, G, B, A uint16
}

func (c RGBA64Color) RGBA() (r, g, b, a uint32) {
	return uint32(c.R), uint32(c.G), uint32(c.B), uint32(c.A)
}

// NRGBAColor represents a non-alpha-premultiplied 32-bit color.
type NRGBAColor struct {
	R, G, B, A uint8
}

func (c NRGBAColor) RGBA() (r, g, b, a uint32) {
	r = uint32(c.R)
	r |= r << 8
	r *= uint32(c.A)
	r /= 0xff
	g = uint32(c.G)
	g |= g << 8
	g *= uint32(c.A)
	g /= 0xff
	b = uint32(c.B)
	b |= b << 8
	b *= uint32(c.A)
	b /= 0xff
	a = uint32(c.A)
	a |= a << 8
	return
}

// NRGBA64Color represents a non-alpha-premultiplied 64-bit color,
// having 16 bits for each of red, green, blue and alpha.
type NRGBA64Color struct {
	R, G, B, A uint16
}

func (c NRGBA64Color) RGBA() (r, g, b, a uint32) {
	r = uint32(c.R)
	r *= uint32(c.A)
	r /= 0xffff
	g = uint32(c.G)
	g *= uint32(c.A)
	g /= 0xffff
	b = uint32(c.B)
	b *= uint32(c.A)
	b /= 0xffff
	a = uint32(c.A)
	return
}

// AlphaColor represents an 8-bit alpha.
type AlphaColor struct {
	A uint8
}

func (c AlphaColor) RGBA() (r, g, b, a uint32) {
	a = uint32(c.A)
	a |= a << 8
	return a, a, a, a
}

// Alpha16Color represents a 16-bit alpha.
type Alpha16Color struct {
	A uint16
}

func (c Alpha16Color) RGBA() (r, g, b, a uint32) {
	a = uint32(c.A)
	return a, a, a, a
}

// GrayColor represents an 8-bit grayscale color.
type GrayColor struct {
	Y uint8
}

func (c GrayColor) RGBA() (r, g, b, a uint32) {
	y := uint32(c.Y)
	y |= y << 8
	return y, y, y, 0xffff
}

// Gray16Color represents a 16-bit grayscale color.
type Gray16Color struct {
	Y uint16
}

func (c Gray16Color) RGBA() (r, g, b, a uint32) {
	y := uint32(c.Y)
	return y, y, y, 0xffff
}

// ColorModel can convert foreign Colors, with a possible loss of precision,
// to a Color from its own color model.
type ColorModel interface {
	Convert(c Color) Color
}

// The ColorModelFunc type is an adapter to allow the use of an ordinary
// color conversion function as a ColorModel.  If f is such a function,
// ColorModelFunc(f) is a ColorModel object that invokes f to implement
// the conversion.
type ColorModelFunc func(Color) Color

func (f ColorModelFunc) Convert(c Color) Color {
	return f(c)
}

func toRGBAColor(c Color) Color {
	if _, ok := c.(RGBAColor); ok {
		return c
	}
	r, g, b, a := c.RGBA()
	return RGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
}

func toRGBA64Color(c Color) Color {
	if _, ok := c.(RGBA64Color); ok {
		return c
	}
	r, g, b, a := c.RGBA()
	return RGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
}

func toNRGBAColor(c Color) Color {
	if _, ok := c.(NRGBAColor); ok {
		return c
	}
	r, g, b, a := c.RGBA()
	if a == 0xffff {
		return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), 0xff}
	}
	if a == 0 {
		return NRGBAColor{0, 0, 0, 0}
	}
	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
	r = (r * 0xffff) / a
	g = (g * 0xffff) / a
	b = (b * 0xffff) / a
	return NRGBAColor{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
}

func toNRGBA64Color(c Color) Color {
	if _, ok := c.(NRGBA64Color); ok {
		return c
	}
	r, g, b, a := c.RGBA()
	if a == 0xffff {
		return NRGBA64Color{uint16(r), uint16(g), uint16(b), 0xffff}
	}
	if a == 0 {
		return NRGBA64Color{0, 0, 0, 0}
	}
	// Since Color.RGBA returns a alpha-premultiplied color, we should have r <= a && g <= a && b <= a.
	r = (r * 0xffff) / a
	g = (g * 0xffff) / a
	b = (b * 0xffff) / a
	return NRGBA64Color{uint16(r), uint16(g), uint16(b), uint16(a)}
}

func toAlphaColor(c Color) Color {
	if _, ok := c.(AlphaColor); ok {
		return c
	}
	_, _, _, a := c.RGBA()
	return AlphaColor{uint8(a >> 8)}
}

func toAlpha16Color(c Color) Color {
	if _, ok := c.(Alpha16Color); ok {
		return c
	}
	_, _, _, a := c.RGBA()
	return Alpha16Color{uint16(a)}
}

func toGrayColor(c Color) Color {
	if _, ok := c.(GrayColor); ok {
		return c
	}
	r, g, b, _ := c.RGBA()
	y := (299*r + 587*g + 114*b + 500) / 1000
	return GrayColor{uint8(y >> 8)}
}

func toGray16Color(c Color) Color {
	if _, ok := c.(Gray16Color); ok {
		return c
	}
	r, g, b, _ := c.RGBA()
	y := (299*r + 587*g + 114*b + 500) / 1000
	return Gray16Color{uint16(y)}
}

// The ColorModel associated with RGBAColor.
var RGBAColorModel ColorModel = ColorModelFunc(toRGBAColor)

// The ColorModel associated with RGBA64Color.
var RGBA64ColorModel ColorModel = ColorModelFunc(toRGBA64Color)

// The ColorModel associated with NRGBAColor.
var NRGBAColorModel ColorModel = ColorModelFunc(toNRGBAColor)

// The ColorModel associated with NRGBA64Color.
var NRGBA64ColorModel ColorModel = ColorModelFunc(toNRGBA64Color)

// The ColorModel associated with AlphaColor.
var AlphaColorModel ColorModel = ColorModelFunc(toAlphaColor)

// The ColorModel associated with Alpha16Color.
var Alpha16ColorModel ColorModel = ColorModelFunc(toAlpha16Color)

// The ColorModel associated with GrayColor.
var GrayColorModel ColorModel = ColorModelFunc(toGrayColor)

// The ColorModel associated with Gray16Color.
var Gray16ColorModel ColorModel = ColorModelFunc(toGray16Color)
<commit_msg>image: delete obsolete color.go<commit_after><|endoftext|>


<commit_before>package tag

import (
	"testing"

	"strconv"
)

func TestNew(t *testing.T) {
	var params = map[string]string{
		"name":   "latest",
		"digest": "sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
	}

	tg, err := New(params["name"], params["digest"])

	if err != nil {
		t.Fatalf("Unable to create new tag: %s", err.Error())
	}

	if tg.GetName() != params["name"] {
		t.Fatalf("Unexpected name: '%s' (expected '%s')", tg.GetName(), params["name"])
	}

	if tg.GetDigest() != params["digest"] {
		t.Fatalf("Unexpected digest: '%s' (expected '%s')", tg.GetDigest(), params["digest"])
	}

	if tg.GetShortDigest() != params["digest"][0:40] {
		t.Fatalf("Unexpected short digest: '%s' (expected '%s')", tg.GetShortDigest(), params["digest"][0:40])
	}
}

func TestNew_WithEmptyName(t *testing.T) {
	_, err := New(
		"",
		"sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
	)

	if err == nil {
		t.Fatalf("Was able to create tag with empty name")
	}
}

func TestNew_WithEmptyDigest(t *testing.T) {
	_, err := New(
		"latest",
		"",
	)

	if err == nil {
		t.Fatalf("Was able to create tag with empty image digest")
	}
}

//
// A pretty "Chinese" way of generating test data here (no pun intended here, no racism).
// But I like it because it's easy and doesn't require creation of extra data structures.
//
func getRemoteTags() map[string]*Tag {
	tags := make(map[string]*Tag, 0)

	tg1, _ := New(
		"latest",
		"sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
	)
	tags["latest"] = tg1

	tg2, _ := New(
		"v1.1",
		"sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
	)
	tags["v1.1"] = tg2

	tg3, _ := New(
		"v1.2",
		"sha256:7f7f94f26d23f7aca80a33732161af068f9f62fbe0e824a58cf3a39d209cfa77",
	)
	tags["v1.2"] = tg3

	tg4, _ := New(
		"v1.3.1",
		"sha256:9fb0e8a4f629b72a0a69aef357e637e4145b6588f04f1540a31a0d2e030ea7da",
	)
	tags["v1.3.1"] = tg4

	tg5, _ := New(
		"v1.3.2",
		"sha256:fc41473fc36c09222a29ffce9eaf5732fae91c3fabfa40aa878f600e13c7fed3",
	)
	tg5.SetContainerID("16dcde7895c73c98161aa6981c4ea0df027697cd")
	tags["v1.3.2"] = tg5

	return tags
}

func getLocalTags() map[string]*Tag {
	tags := make(map[string]*Tag, 0)

	tg1, _ := New(
		"latest",
		"sha256:8ffc20b5be0e391f07f270bf79441fbea3c8b67200e5316bdefad9e0ca80277b",
	)
	tg1.SetImageID("sha256:883e3a5b24d7b46f81436bfc85564a676aa021a2c8adedc3ac6ab12ac06fdd95")
	tags["latest"] = tg1

	tg2, _ := New(
		"v1.0",
		"sha256:fe4286e7b852dc6aad6225239ecb32691f15f20b0d4354defb4ca4957958b2f0",
	)
	tg2.SetImageID("sha256:c9a69a36ff3ce76d7970df83bd438f0f1bc0363a3b4707b42542ea20ba4282f4")
	tags["v1.0"] = tg2

	tg3, _ := New(
		"v1.2",
		"sha256:7f7f94f26d23f7aca80a33732161af068f9f62fbe0e824a58cf3a39d209cfa77",
	)
	tg3.SetImageID("sha256:4c4ebb9614ef823bd04e5eba65e59286a4314d3a063e2eaa221d38fc21723cea")
	tags["v1.2"] = tg3

	tg4, _ := New(
		"v1.3.1",
		"sha256:7264ba7450b6be1bfba9ab29f506293bb324f4764c41ff32dcc04379c1a69c91",
	)
	tags["v1.3.1"] = tg4

	tg5, _ := New(
		"v1.3.2",
		"sha256:70fbfacca0ab3ec01258b1787b02de77474c6f120b86bb8743b81b7dc37d4aab",
	)
	tg5.SetContainerID("16dcde7895c73c98161aa6981c4ea0df027697cd")
	tags["v1.3.2"] = tg5

	return tags
}

//
// Join() is a "heart" of the `tag` package.
// It requires much love & reliable testing!
//
func TestJoin_Length(t *testing.T) {
	const expected = 6

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	length := len(tags)

	if length != expected {
		t.Fatalf(
			"Unexpected number of joined tags: %s (expected: %s)",
			strconv.Itoa(length),
			strconv.Itoa(expected),
		)
	}
}

func TestJoin_Digest(t *testing.T) {
	examples := map[string]string{
		"latest": "sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
		"v1.0":   "sha256:fe4286e7b852dc6aad6225239ecb32691f15f20b0d4354defb4ca4957958b2f0",
		"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
		"v1.2":   "sha256:7f7f94f26d23f7aca80a33732161af068f9f62fbe0e824a58cf3a39d209cfa77",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		digest := tags[name].GetDigest()

		if digest != expected {
			t.Fatalf(
				"Unexpected digest [%s]: %s (expected: %s)",
				name,
				digest,
				expected,
			)
		}
	}
}

func TestJoin_ImageID(t *testing.T) {
	examples := map[string]string{
		"latest": "883e3a5b24d7",
		"v1.0":   "c9a69a36ff3c",
		"v1.1":   "n/a",
		"v1.2":   "4c4ebb9614ef",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		imageID := tags[name].GetImageID()

		if imageID != expected {
			t.Fatalf(
				"Unexpected image ID [%s]: %s (expected: %s)",
				name,
				imageID,
				expected,
			)
		}
	}
}

func TestJoin_State(t *testing.T) {
	examples := map[string]string{
		"latest": "CHANGED",
		"v1.0":   "LOCAL-ONLY",
		"v1.1":   "ABSENT",
		"v1.2":   "PRESENT",
		"v1.3.1": "CHANGED",
		"v1.3.2": "PRESENT",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		state := tags[name].GetState()

		if state != expected {
			t.Fatalf(
				"Unexpected state [%s]: %s (expected: %s)",
				name,
				state,
				expected,
			)
		}
	}
}

func TestJoin_State_WithAssumedTagNames(t *testing.T) {
	assumedTagNames := []string{"v1.3.2", "v1.4.1"}

	examples := map[string]string{
		"v1.3.2": "PRESENT",
		"v1.4.1": "ASSUMED",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), assumedTagNames)

	for name, expected := range examples {
		state := tags[name].GetState()

		if state != expected {
			t.Fatalf(
				"Unexpected state [%s]: %s (expected: %s)",
				name,
				state,
				expected,
			)
		}
	}
}

func TestJoin_NeedsPush(t *testing.T) {
	examples := map[string]bool{
		"v1.3.1": false,
		"v1.3.2": false,
	}
	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		needsPush := tags[name].NeedsPush(false)

		if needsPush != expected {
			t.Fatalf(
				"Unexpected push need [%s]: %v (expected: %v)",
				name,
				needsPush,
				expected,
			)
		}
	}
}

func TestJoin_NeedsPush_WithPushUpdate(t *testing.T) {
	examples := map[string]bool{
		"v1.3.1": true,
		"v1.3.2": false,
	}
	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		needsPush := tags[name].NeedsPush(true)

		if needsPush != expected {
			t.Fatalf(
				"Unexpected push need [%s]: %v (expected: %v)",
				name,
				needsPush,
				expected,
			)
		}
	}
}
<commit_msg>NORELEASE: Test the Collect() func<commit_after>package tag

import (
	"testing"

	"strconv"
)

func TestNew(t *testing.T) {
	var params = map[string]string{
		"name":   "latest",
		"digest": "sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
	}

	tg, err := New(params["name"], params["digest"])

	if err != nil {
		t.Fatalf("Unable to create new tag: %s", err.Error())
	}

	if tg.GetName() != params["name"] {
		t.Fatalf("Unexpected name: '%s' (expected '%s')", tg.GetName(), params["name"])
	}

	if tg.GetDigest() != params["digest"] {
		t.Fatalf("Unexpected digest: '%s' (expected '%s')", tg.GetDigest(), params["digest"])
	}

	if tg.GetShortDigest() != params["digest"][0:40] {
		t.Fatalf("Unexpected short digest: '%s' (expected '%s')", tg.GetShortDigest(), params["digest"][0:40])
	}
}

func TestNew_WithEmptyName(t *testing.T) {
	_, err := New(
		"",
		"sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
	)

	if err == nil {
		t.Fatalf("Was able to create tag with empty name")
	}
}

func TestNew_WithEmptyDigest(t *testing.T) {
	_, err := New(
		"latest",
		"",
	)

	if err == nil {
		t.Fatalf("Was able to create tag with empty image digest")
	}
}

//
// A pretty "Chinese" way of generating test data here (no pun intended here, no racism).
// But I like it because it's easy and doesn't require creation of extra data structures.
//
func getRemoteTags() map[string]*Tag {
	tags := make(map[string]*Tag, 0)

	tg1, _ := New(
		"latest",
		"sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
	)
	tags["latest"] = tg1

	tg2, _ := New(
		"v1.1",
		"sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
	)
	tags["v1.1"] = tg2

	tg3, _ := New(
		"v1.2",
		"sha256:7f7f94f26d23f7aca80a33732161af068f9f62fbe0e824a58cf3a39d209cfa77",
	)
	tags["v1.2"] = tg3

	tg4, _ := New(
		"v1.3.1",
		"sha256:9fb0e8a4f629b72a0a69aef357e637e4145b6588f04f1540a31a0d2e030ea7da",
	)
	tags["v1.3.1"] = tg4

	tg5, _ := New(
		"v1.3.2",
		"sha256:fc41473fc36c09222a29ffce9eaf5732fae91c3fabfa40aa878f600e13c7fed3",
	)
	tg5.SetContainerID("16dcde7895c73c98161aa6981c4ea0df027697cd")
	tags["v1.3.2"] = tg5

	return tags
}

func getLocalTags() map[string]*Tag {
	tags := make(map[string]*Tag, 0)

	tg1, _ := New(
		"latest",
		"sha256:8ffc20b5be0e391f07f270bf79441fbea3c8b67200e5316bdefad9e0ca80277b",
	)
	tg1.SetImageID("sha256:883e3a5b24d7b46f81436bfc85564a676aa021a2c8adedc3ac6ab12ac06fdd95")
	tags["latest"] = tg1

	tg2, _ := New(
		"v1.0",
		"sha256:fe4286e7b852dc6aad6225239ecb32691f15f20b0d4354defb4ca4957958b2f0",
	)
	tg2.SetImageID("sha256:c9a69a36ff3ce76d7970df83bd438f0f1bc0363a3b4707b42542ea20ba4282f4")
	tags["v1.0"] = tg2

	tg3, _ := New(
		"v1.2",
		"sha256:7f7f94f26d23f7aca80a33732161af068f9f62fbe0e824a58cf3a39d209cfa77",
	)
	tg3.SetImageID("sha256:4c4ebb9614ef823bd04e5eba65e59286a4314d3a063e2eaa221d38fc21723cea")
	tags["v1.2"] = tg3

	tg4, _ := New(
		"v1.3.1",
		"sha256:7264ba7450b6be1bfba9ab29f506293bb324f4764c41ff32dcc04379c1a69c91",
	)
	tags["v1.3.1"] = tg4

	tg5, _ := New(
		"v1.3.2",
		"sha256:70fbfacca0ab3ec01258b1787b02de77474c6f120b86bb8743b81b7dc37d4aab",
	)
	tg5.SetContainerID("16dcde7895c73c98161aa6981c4ea0df027697cd")
	tags["v1.3.2"] = tg5

	return tags
}

//
// Join() is a "heart" of the `tag` package.
// It requires much love & reliable testing!
//
func TestJoin_Length(t *testing.T) {
	const expected = 6

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	length := len(tags)

	if length != expected {
		t.Fatalf(
			"Unexpected number of joined tags: %s (expected: %s)",
			strconv.Itoa(length),
			strconv.Itoa(expected),
		)
	}
}

func TestJoin_Digest(t *testing.T) {
	examples := map[string]string{
		"latest": "sha256:c92260fe6357ac1cdd79e86e23fa287701c5edd2921d243a253fd21c9f0012ae",
		"v1.0":   "sha256:fe4286e7b852dc6aad6225239ecb32691f15f20b0d4354defb4ca4957958b2f0",
		"v1.1":   "sha256:7abd16433f3bec5ee4c566ddbfc0e5255678498d5e7e2da8f41393bfe84bfcac",
		"v1.2":   "sha256:7f7f94f26d23f7aca80a33732161af068f9f62fbe0e824a58cf3a39d209cfa77",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		digest := tags[name].GetDigest()

		if digest != expected {
			t.Fatalf(
				"Unexpected digest [%s]: %s (expected: %s)",
				name,
				digest,
				expected,
			)
		}
	}
}

func TestJoin_ImageID(t *testing.T) {
	examples := map[string]string{
		"latest": "883e3a5b24d7",
		"v1.0":   "c9a69a36ff3c",
		"v1.1":   "n/a",
		"v1.2":   "4c4ebb9614ef",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		imageID := tags[name].GetImageID()

		if imageID != expected {
			t.Fatalf(
				"Unexpected image ID [%s]: %s (expected: %s)",
				name,
				imageID,
				expected,
			)
		}
	}
}

func TestJoin_State(t *testing.T) {
	examples := map[string]string{
		"latest": "CHANGED",
		"v1.0":   "LOCAL-ONLY",
		"v1.1":   "ABSENT",
		"v1.2":   "PRESENT",
		"v1.3.1": "CHANGED",
		"v1.3.2": "PRESENT",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		state := tags[name].GetState()

		if state != expected {
			t.Fatalf(
				"Unexpected state [%s]: %s (expected: %s)",
				name,
				state,
				expected,
			)
		}
	}
}

func TestJoin_State_WithAssumedTagNames(t *testing.T) {
	assumedTagNames := []string{"v1.3.2", "v1.4.1"}

	examples := map[string]string{
		"v1.3.2": "PRESENT",
		"v1.4.1": "ASSUMED",
	}

	_, _, tags := Join(getRemoteTags(), getLocalTags(), assumedTagNames)

	for name, expected := range examples {
		state := tags[name].GetState()

		if state != expected {
			t.Fatalf(
				"Unexpected state [%s]: %s (expected: %s)",
				name,
				state,
				expected,
			)
		}
	}
}

func TestJoin_NeedsPush(t *testing.T) {
	examples := map[string]bool{
		"v1.3.1": false,
		"v1.3.2": false,
	}
	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		needsPush := tags[name].NeedsPush(false)

		if needsPush != expected {
			t.Fatalf(
				"Unexpected push need [%s]: %v (expected: %v)",
				name,
				needsPush,
				expected,
			)
		}
	}
}

func TestJoin_NeedsPush_WithPushUpdate(t *testing.T) {
	examples := map[string]bool{
		"v1.3.1": true,
		"v1.3.2": false,
	}
	_, _, tags := Join(getRemoteTags(), getLocalTags(), nil)

	for name, expected := range examples {
		needsPush := tags[name].NeedsPush(true)

		if needsPush != expected {
			t.Fatalf(
				"Unexpected push need [%s]: %v (expected: %v)",
				name,
				needsPush,
				expected,
			)
		}
	}
}

func TestCollect(t *testing.T) {
	keys, tagNames, tagMap := Join(getRemoteTags(), getLocalTags(), nil)

	tags := Collect(keys, tagNames, tagMap)

	if len(tags) != len(tagMap) {
		t.Fatalf(
			"number of tags is not equal to one of original map (%d vs %d)\n%+v\nvs\n%+v",
			len(tags),
			len(tagMap),
			tags,
			tagMap,
		)
	}

	for _, tg := range tags {
		_, defined := tagMap[tg.GetName()]

		if !defined {
			t.Fatalf(
				"tag '%s' (from %+v) not present in original map: %+v",
				tg.GetName(),
				tags,
				tagMap,
			)
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Marshalling and unmarshalling of
// JSON data into Go structs using reflection.

package json

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"reflect"
	"strings"
)

type structBuilder struct {
	val reflect.Value

	// if map_ != nil, write val to map_[key] on each change
	map_ *reflect.MapValue
	key  reflect.Value
}

var nobuilder *structBuilder

func isfloat(v reflect.Value) bool {
	switch v.(type) {
	case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value:
		return true
	}
	return false
}

func setfloat(v reflect.Value, f float64) {
	switch v := v.(type) {
	case *reflect.FloatValue:
		v.Set(float(f))
	case *reflect.Float32Value:
		v.Set(float32(f))
	case *reflect.Float64Value:
		v.Set(float64(f))
	}
}

func setint(v reflect.Value, i int64) {
	switch v := v.(type) {
	case *reflect.IntValue:
		v.Set(int(i))
	case *reflect.Int8Value:
		v.Set(int8(i))
	case *reflect.Int16Value:
		v.Set(int16(i))
	case *reflect.Int32Value:
		v.Set(int32(i))
	case *reflect.Int64Value:
		v.Set(int64(i))
	case *reflect.UintValue:
		v.Set(uint(i))
	case *reflect.Uint8Value:
		v.Set(uint8(i))
	case *reflect.Uint16Value:
		v.Set(uint16(i))
	case *reflect.Uint32Value:
		v.Set(uint32(i))
	case *reflect.Uint64Value:
		v.Set(uint64(i))
	}
}

// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func (b *structBuilder) Flush() {
	if b == nil {
		return
	}
	if b.map_ != nil {
		b.map_.SetElem(b.key, b.val)
	}
}

func (b *structBuilder) Int64(i int64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, i)
	}
}

func (b *structBuilder) Uint64(i uint64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, int64(i))
	}
}

func (b *structBuilder) Float64(f float64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, f)
	} else {
		setint(v, int64(f))
	}
}

func (b *structBuilder) Null() {}

func (b *structBuilder) String(s string) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.StringValue); ok {
		v.Set(s)
	}
}

func (b *structBuilder) Bool(tf bool) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.BoolValue); ok {
		v.Set(tf)
	}
}

func (b *structBuilder) Array() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.SliceValue); ok {
		if v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8))
		}
	}
}

func (b *structBuilder) Elem(i int) Builder {
	if b == nil || i < 0 {
		return nobuilder
	}
	switch v := b.val.(type) {
	case *reflect.ArrayValue:
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	case *reflect.SliceValue:
		if i >= v.Cap() {
			n := v.Cap()
			if n < 8 {
				n = 8
			}
			for n <= i {
				n *= 2
			}
			nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n)
			reflect.ArrayCopy(nv, v)
			v.Set(nv)
		}
		if v.Len() <= i && i < v.Cap() {
			v.SetLen(i + 1)
		}
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	}
	return nobuilder
}

func (b *structBuilder) Map() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			b.Flush()
		}
		b.map_ = nil
		b.val = v.Elem()
	}
	if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}

func (b *structBuilder) Key(k string) Builder {
	if b == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(b.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			if strings.ToLower(t.Field(i).Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}
	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}
	}
	return nobuilder
}

// Unmarshal parses the JSON syntax string s and fills in
// an arbitrary struct or slice pointed at by val.
// It uses the reflect package to assign to fields
// and arrays embedded in val.  Well-formed data that does not fit
// into the struct is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string;
//		Addr string;
//	}
//
//	type Result struct {
//		Name string;
//		Phone string;
//		Email []Email
//	}
//
//	var r = Result{ "name", "phone", nil }
//
// unmarshalling the JSON syntax string
//
//	{
//	  "email": [
//	    {
//	      "where": "home",
//	      "addr": "gre@example.com"
//	    },
//	    {
//	      "where": "work",
//	      "addr": "gre@work.com"
//	    }
//	  ],
//	  "name": "Grace R. Emlin",
//	  "address": "123 Main Street"
//	}
//
// via Unmarshal(s, &r) is equivalent to assigning
//
//	r = Result{
//		"Grace R. Emlin",	// name
//		"phone",		// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" }
//		}
//	}
//
// Note that the field r.Phone has not been modified and
// that the JSON field "address" was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match JSON field names to struct field names.
//
// To unmarshal a top-level JSON array, pass in a pointer to an empty
// slice of the correct type.
//
// On success, Unmarshal returns with ok set to true.
// On a syntax error, it returns with ok set to false and errtok
// set to the offending token.
func Unmarshal(s string, val interface{}) (ok bool, errtok string) {
	v := reflect.NewValue(val)
	var b *structBuilder

	// If val is a pointer to a slice, we append to the slice.
	if ptr, ok := v.(*reflect.PtrValue); ok {
		if slice, ok := ptr.Elem().(*reflect.SliceValue); ok {
			b = &structBuilder{val: slice}
		}
	}

	if b == nil {
		b = &structBuilder{val: v}
	}

	ok, _, errtok = Parse(s, b)
	if !ok {
		return false, errtok
	}
	return true, ""
}

type MarshalError struct {
	T reflect.Type
}

func (e *MarshalError) String() string {
	return "json cannot encode value of type " + e.T.String()
}

type writeState struct {
	bytes.Buffer
	indent   string
	newlines bool
	depth    int
}

func (s *writeState) descend(bra byte) {
	s.depth++
	s.WriteByte(bra)
}

func (s *writeState) ascend(ket byte) {
	s.depth--
	s.writeIndent()
	s.WriteByte(ket)
}

func (s *writeState) writeIndent() {
	if s.newlines {
		s.WriteByte('\n')
	}
	for i := 0; i < s.depth; i++ {
		s.WriteString(s.indent)
	}
}

func (s *writeState) writeArrayOrSlice(val reflect.ArrayOrSliceValue) (err os.Error) {
	s.descend('[')

	for i := 0; i < val.Len(); i++ {
		s.writeIndent()

		if err = s.writeValue(val.Elem(i)); err != nil {
			return
		}

		if i < val.Len()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend(']')
	return
}

func (s *writeState) writeMap(val *reflect.MapValue) (err os.Error) {
	key := val.Type().(*reflect.MapType).Key()
	if _, ok := key.(*reflect.StringType); !ok {
		return &MarshalError{val.Type()}
	}

	s.descend('{')

	keys := val.Keys()
	for i := 0; i < len(keys); i++ {
		s.writeIndent()

		fmt.Fprintf(s, "%s:", Quote(keys[i].(*reflect.StringValue).Get()))

		if err = s.writeValue(val.Elem(keys[i])); err != nil {
			return
		}

		if i < len(keys)-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
	return
}

func (s *writeState) writeStruct(val *reflect.StructValue) (err os.Error) {
	s.descend('{')

	typ := val.Type().(*reflect.StructType)

	for i := 0; i < val.NumField(); i++ {
		s.writeIndent()

		fieldValue := val.Field(i)
		fmt.Fprintf(s, "%s:", Quote(typ.Field(i).Name))
		if err = s.writeValue(fieldValue); err != nil {
			return
		}
		if i < val.NumField()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
	return
}

func (s *writeState) writeValue(val reflect.Value) (err os.Error) {
	if val == nil {
		fmt.Fprint(s, "null")
		return
	}

	switch v := val.(type) {
	case *reflect.StringValue:
		fmt.Fprint(s, Quote(v.Get()))
	case *reflect.ArrayValue:
		err = s.writeArrayOrSlice(v)
	case *reflect.SliceValue:
		err = s.writeArrayOrSlice(v)
	case *reflect.MapValue:
		err = s.writeMap(v)
	case *reflect.StructValue:
		err = s.writeStruct(v)
	case *reflect.ChanValue,
		*reflect.UnsafePointerValue,
		*reflect.FuncValue:
		err = &MarshalError{val.Type()}
	case *reflect.InterfaceValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			err = s.writeValue(v.Elem())
		}
	case *reflect.PtrValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			err = s.writeValue(v.Elem())
		}
	case *reflect.UintptrValue:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint64Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint32Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint16Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint8Value:
		fmt.Fprintf(s, "%d", v.Get())
	default:
		value := val.(reflect.Value)
		fmt.Fprintf(s, "%#v", value.Interface())
	}
	return
}

func (s *writeState) marshal(w io.Writer, val interface{}) (err os.Error) {
	err = s.writeValue(reflect.NewValue(val))
	if err != nil {
		return
	}
	if s.newlines {
		s.WriteByte('\n')
	}
	_, err = s.WriteTo(w)
	return
}

// Marshal writes the JSON encoding of val to w.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func Marshal(w io.Writer, val interface{}) os.Error {
	s := &writeState{indent: "", newlines: false, depth: 0}
	return s.marshal(w, val)
}

// MarshalIndent writes the JSON encoding of val to w,
// indenting nested values using the indent string.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func MarshalIndent(w io.Writer, val interface{}, indent string) os.Error {
	s := &writeState{indent: indent, newlines: true, depth: 0}
	return s.marshal(w, val)
}
<commit_msg>json: use panic/recover to handle errors in Marshal<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Marshalling and unmarshalling of
// JSON data into Go structs using reflection.

package json

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"reflect"
	"strings"
)

type structBuilder struct {
	val reflect.Value

	// if map_ != nil, write val to map_[key] on each change
	map_ *reflect.MapValue
	key  reflect.Value
}

var nobuilder *structBuilder

func isfloat(v reflect.Value) bool {
	switch v.(type) {
	case *reflect.FloatValue, *reflect.Float32Value, *reflect.Float64Value:
		return true
	}
	return false
}

func setfloat(v reflect.Value, f float64) {
	switch v := v.(type) {
	case *reflect.FloatValue:
		v.Set(float(f))
	case *reflect.Float32Value:
		v.Set(float32(f))
	case *reflect.Float64Value:
		v.Set(float64(f))
	}
}

func setint(v reflect.Value, i int64) {
	switch v := v.(type) {
	case *reflect.IntValue:
		v.Set(int(i))
	case *reflect.Int8Value:
		v.Set(int8(i))
	case *reflect.Int16Value:
		v.Set(int16(i))
	case *reflect.Int32Value:
		v.Set(int32(i))
	case *reflect.Int64Value:
		v.Set(int64(i))
	case *reflect.UintValue:
		v.Set(uint(i))
	case *reflect.Uint8Value:
		v.Set(uint8(i))
	case *reflect.Uint16Value:
		v.Set(uint16(i))
	case *reflect.Uint32Value:
		v.Set(uint32(i))
	case *reflect.Uint64Value:
		v.Set(uint64(i))
	}
}

// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func (b *structBuilder) Flush() {
	if b == nil {
		return
	}
	if b.map_ != nil {
		b.map_.SetElem(b.key, b.val)
	}
}

func (b *structBuilder) Int64(i int64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, i)
	}
}

func (b *structBuilder) Uint64(i uint64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, float64(i))
	} else {
		setint(v, int64(i))
	}
}

func (b *structBuilder) Float64(f float64) {
	if b == nil {
		return
	}
	v := b.val
	if isfloat(v) {
		setfloat(v, f)
	} else {
		setint(v, int64(f))
	}
}

func (b *structBuilder) Null() {}

func (b *structBuilder) String(s string) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.StringValue); ok {
		v.Set(s)
	}
}

func (b *structBuilder) Bool(tf bool) {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.BoolValue); ok {
		v.Set(tf)
	}
}

func (b *structBuilder) Array() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.SliceValue); ok {
		if v.IsNil() {
			v.Set(reflect.MakeSlice(v.Type().(*reflect.SliceType), 0, 8))
		}
	}
}

func (b *structBuilder) Elem(i int) Builder {
	if b == nil || i < 0 {
		return nobuilder
	}
	switch v := b.val.(type) {
	case *reflect.ArrayValue:
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	case *reflect.SliceValue:
		if i >= v.Cap() {
			n := v.Cap()
			if n < 8 {
				n = 8
			}
			for n <= i {
				n *= 2
			}
			nv := reflect.MakeSlice(v.Type().(*reflect.SliceType), v.Len(), n)
			reflect.ArrayCopy(nv, v)
			v.Set(nv)
		}
		if v.Len() <= i && i < v.Cap() {
			v.SetLen(i + 1)
		}
		if i < v.Len() {
			return &structBuilder{val: v.Elem(i)}
		}
	}
	return nobuilder
}

func (b *structBuilder) Map() {
	if b == nil {
		return
	}
	if v, ok := b.val.(*reflect.PtrValue); ok && v.IsNil() {
		if v.IsNil() {
			v.PointTo(reflect.MakeZero(v.Type().(*reflect.PtrType).Elem()))
			b.Flush()
		}
		b.map_ = nil
		b.val = v.Elem()
	}
	if v, ok := b.val.(*reflect.MapValue); ok && v.IsNil() {
		v.Set(reflect.MakeMap(v.Type().(*reflect.MapType)))
	}
}

func (b *structBuilder) Key(k string) Builder {
	if b == nil {
		return nobuilder
	}
	switch v := reflect.Indirect(b.val).(type) {
	case *reflect.StructValue:
		t := v.Type().(*reflect.StructType)
		// Case-insensitive field lookup.
		k = strings.ToLower(k)
		for i := 0; i < t.NumField(); i++ {
			if strings.ToLower(t.Field(i).Name) == k {
				return &structBuilder{val: v.Field(i)}
			}
		}
	case *reflect.MapValue:
		t := v.Type().(*reflect.MapType)
		if t.Key() != reflect.Typeof(k) {
			break
		}
		key := reflect.NewValue(k)
		elem := v.Elem(key)
		if elem == nil {
			v.SetElem(key, reflect.MakeZero(t.Elem()))
			elem = v.Elem(key)
		}
		return &structBuilder{val: elem, map_: v, key: key}
	}
	return nobuilder
}

// Unmarshal parses the JSON syntax string s and fills in
// an arbitrary struct or slice pointed at by val.
// It uses the reflect package to assign to fields
// and arrays embedded in val.  Well-formed data that does not fit
// into the struct is discarded.
//
// For example, given these definitions:
//
//	type Email struct {
//		Where string;
//		Addr string;
//	}
//
//	type Result struct {
//		Name string;
//		Phone string;
//		Email []Email
//	}
//
//	var r = Result{ "name", "phone", nil }
//
// unmarshalling the JSON syntax string
//
//	{
//	  "email": [
//	    {
//	      "where": "home",
//	      "addr": "gre@example.com"
//	    },
//	    {
//	      "where": "work",
//	      "addr": "gre@work.com"
//	    }
//	  ],
//	  "name": "Grace R. Emlin",
//	  "address": "123 Main Street"
//	}
//
// via Unmarshal(s, &r) is equivalent to assigning
//
//	r = Result{
//		"Grace R. Emlin",	// name
//		"phone",		// no phone given
//		[]Email{
//			Email{ "home", "gre@example.com" },
//			Email{ "work", "gre@work.com" }
//		}
//	}
//
// Note that the field r.Phone has not been modified and
// that the JSON field "address" was discarded.
//
// Because Unmarshal uses the reflect package, it can only
// assign to upper case fields.  Unmarshal uses a case-insensitive
// comparison to match JSON field names to struct field names.
//
// To unmarshal a top-level JSON array, pass in a pointer to an empty
// slice of the correct type.
//
// On success, Unmarshal returns with ok set to true.
// On a syntax error, it returns with ok set to false and errtok
// set to the offending token.
func Unmarshal(s string, val interface{}) (ok bool, errtok string) {
	v := reflect.NewValue(val)
	var b *structBuilder

	// If val is a pointer to a slice, we append to the slice.
	if ptr, ok := v.(*reflect.PtrValue); ok {
		if slice, ok := ptr.Elem().(*reflect.SliceValue); ok {
			b = &structBuilder{val: slice}
		}
	}

	if b == nil {
		b = &structBuilder{val: v}
	}

	ok, _, errtok = Parse(s, b)
	if !ok {
		return false, errtok
	}
	return true, ""
}

type MarshalError struct {
	T reflect.Type
}

func (e *MarshalError) String() string {
	return "json cannot encode value of type " + e.T.String()
}

type writeState struct {
	bytes.Buffer
	indent   string
	newlines bool
	depth    int
}

func (s *writeState) descend(bra byte) {
	s.depth++
	s.WriteByte(bra)
}

func (s *writeState) ascend(ket byte) {
	s.depth--
	s.writeIndent()
	s.WriteByte(ket)
}

func (s *writeState) writeIndent() {
	if s.newlines {
		s.WriteByte('\n')
	}
	for i := 0; i < s.depth; i++ {
		s.WriteString(s.indent)
	}
}

func (s *writeState) writeArrayOrSlice(val reflect.ArrayOrSliceValue) {
	s.descend('[')

	for i := 0; i < val.Len(); i++ {
		s.writeIndent()
		s.writeValue(val.Elem(i))
		if i < val.Len()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend(']')
}

func (s *writeState) writeMap(val *reflect.MapValue) {
	key := val.Type().(*reflect.MapType).Key()
	if _, ok := key.(*reflect.StringType); !ok {
		panic(&MarshalError{val.Type()})
	}

	s.descend('{')

	keys := val.Keys()
	for i := 0; i < len(keys); i++ {
		s.writeIndent()
		fmt.Fprintf(s, "%s:", Quote(keys[i].(*reflect.StringValue).Get()))
		s.writeValue(val.Elem(keys[i]))
		if i < len(keys)-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
}

func (s *writeState) writeStruct(val *reflect.StructValue) {
	s.descend('{')

	typ := val.Type().(*reflect.StructType)

	for i := 0; i < val.NumField(); i++ {
		s.writeIndent()
		fmt.Fprintf(s, "%s:", Quote(typ.Field(i).Name))
		s.writeValue(val.Field(i))
		if i < val.NumField()-1 {
			s.WriteByte(',')
		}
	}

	s.ascend('}')
}

func (s *writeState) writeValue(val reflect.Value) {
	if val == nil {
		fmt.Fprint(s, "null")
		return
	}

	switch v := val.(type) {
	case *reflect.StringValue:
		fmt.Fprint(s, Quote(v.Get()))
	case *reflect.ArrayValue:
		s.writeArrayOrSlice(v)
	case *reflect.SliceValue:
		s.writeArrayOrSlice(v)
	case *reflect.MapValue:
		s.writeMap(v)
	case *reflect.StructValue:
		s.writeStruct(v)
	case *reflect.ChanValue,
		*reflect.UnsafePointerValue,
		*reflect.FuncValue:
		panic(&MarshalError{val.Type()})
	case *reflect.InterfaceValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			s.writeValue(v.Elem())
		}
	case *reflect.PtrValue:
		if v.IsNil() {
			fmt.Fprint(s, "null")
		} else {
			s.writeValue(v.Elem())
		}
	case *reflect.UintptrValue:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint64Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint32Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint16Value:
		fmt.Fprintf(s, "%d", v.Get())
	case *reflect.Uint8Value:
		fmt.Fprintf(s, "%d", v.Get())
	default:
		value := val.(reflect.Value)
		fmt.Fprintf(s, "%#v", value.Interface())
	}
}

func (s *writeState) marshal(w io.Writer, val interface{}) (err os.Error) {
	defer func() {
		if e := recover(); e != nil {
			err = e.(*MarshalError)
		}
	}()
	s.writeValue(reflect.NewValue(val))
	if s.newlines {
		s.WriteByte('\n')
	}
	_, err = s.WriteTo(w)
	return
}

// Marshal writes the JSON encoding of val to w.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func Marshal(w io.Writer, val interface{}) os.Error {
	s := &writeState{indent: "", newlines: false, depth: 0}
	return s.marshal(w, val)
}

// MarshalIndent writes the JSON encoding of val to w,
// indenting nested values using the indent string.
//
// Due to limitations in JSON, val cannot include cyclic data
// structures, channels, functions, or maps.
func MarshalIndent(w io.Writer, val interface{}, indent string) os.Error {
	s := &writeState{indent: indent, newlines: true, depth: 0}
	return s.marshal(w, val)
}
<|endoftext|>


<commit_before>package kingpin

// Default usage template.
var DefaultUsageTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
  {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
{{.Help|Wrap 4}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\

{{if .Context.SelectedCommand}}\
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
{{else}}\
usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end}}\
{{if .Context.Flags}}\
Flags:
{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
{{if len .Context.SelectedCommand.Commands}}\
Subcommands:
{{template "FormatCommands" .Context.SelectedCommand}}
{{end}}\
{{else if .App.Commands}}\
Commands:
{{template "FormatCommands" .App}}
{{end}}\
`

// Usage template where command's optional flags are listed separately
var SeparateOptionalFlagsUsageTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
  {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
{{.Help|Wrap 4}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\
{{if .Context.SelectedCommand}}\
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
{{else}}\
usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end}}\

{{if .Context.Flags|RequiredFlags}}\
Required flags:
{{.Context.Flags|RequiredFlags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if  .Context.Flags|OptionalFlags}}\
Optional flags:
{{.Context.Flags|OptionalFlags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
Subcommands:
{{if .Context.SelectedCommand.Commands}}\
{{template "FormatCommands" .Context.SelectedCommand}}
{{end}}\
{{else if .App.Commands}}\
Commands:
{{template "FormatCommands" .App}}
{{end}}\
`

// Usage template with compactly formatted commands.
var CompactUsageTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommandList"}}\
{{range .}}\
{{if not .Hidden}}\
{{.Depth|Indent}}{{.Name}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
{{end}}\
{{template "FormatCommandList" .Commands}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\

{{if .Context.SelectedCommand}}\
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
{{else}}\
usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end}}\
{{if .Context.Flags}}\
Flags:
{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
{{if .Context.SelectedCommand.Commands}}\
Commands:
  {{.Context.SelectedCommand}}
{{template "FormatCommandList" .Context.SelectedCommand.Commands}}
{{end}}\
{{else if .App.Commands}}\
Commands:
{{template "FormatCommandList" .App.Commands}}
{{end}}\
`

var ManPageTemplate = `{{define "FormatFlags"}}\
{{range .Flags}}\
{{if not .Hidden}}\
.TP
\fB{{if .Short}}-{{.Short|Char}}, {{end}}--{{.Name}}{{if not .IsBoolFlag}}={{.FormatPlaceHolder}}{{end}}\\fR
{{.Help}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
.SS
\fB{{.FullCommand}}{{template "FormatCommand" .}}\\fR
.PP
{{.Help}}
{{template "FormatFlags" .}}\
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}\\fR
{{end}}\

.TH {{.App.Name}} 1 {{.App.Version}} "{{.App.Author}}"
.SH "NAME"
{{.App.Name}}
.SH "SYNOPSIS"
.TP
\fB{{.App.Name}}{{template "FormatUsage" .App}}
.SH "DESCRIPTION"
{{.App.Help}}
.SH "OPTIONS"
{{template "FormatFlags" .App}}\
{{if .App.Commands}}\
.SH "COMMANDS"
{{template "FormatCommands" .App}}\
{{end}}\
`

// Default usage template.
var LongHelpTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
  {{.FullCommand}}{{template "FormatCommand" .}}
{{.Help|Wrap 4}}
{{with .Flags|FlagsToTwoColumns}}{{FormatTwoColumnsWithIndent . 4 2}}{{end}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\

usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{if .Context.Flags}}\
Flags:
{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .App.Commands}}\
Commands:
{{template "FormatCommands" .App}}
{{end}}\
`

var BashCompletionTemplate = `
_{{.App.Name}}_bash_autocomplete() {
    local cur prev opts base
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    opts=$( ${COMP_WORDS[0]} --completion-bash "${COMP_WORDS[@]:1:$COMP_CWORD}" )
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
    return 0
}
complete -F _{{.App.Name}}_bash_autocomplete -o default {{.App.Name}}

`

var ZshCompletionTemplate = `
#compdef {{.App.Name}}

_{{.App.Name}}() {
    local matches=($(${words[1]} --completion-bash "${(@)words[1,$CURRENT]}"))
    compadd -a matches

    if [[ $compstate[nmatches] -eq 0 && $words[$CURRENT] != -* ]]; then
        _files
    fi
}

if [[ "$(basename -- ${(%):-%x})" != "_{{.App.Name}}" ]]; then
    compdef _{{.App.Name}} {{.App.Name}}
fi
`
<commit_msg>Remove newline before #compdef<commit_after>package kingpin

// Default usage template.
var DefaultUsageTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
  {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
{{.Help|Wrap 4}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\

{{if .Context.SelectedCommand}}\
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
{{else}}\
usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end}}\
{{if .Context.Flags}}\
Flags:
{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
{{if len .Context.SelectedCommand.Commands}}\
Subcommands:
{{template "FormatCommands" .Context.SelectedCommand}}
{{end}}\
{{else if .App.Commands}}\
Commands:
{{template "FormatCommands" .App}}
{{end}}\
`

// Usage template where command's optional flags are listed separately
var SeparateOptionalFlagsUsageTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
  {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
{{.Help|Wrap 4}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\
{{if .Context.SelectedCommand}}\
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
{{else}}\
usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end}}\

{{if .Context.Flags|RequiredFlags}}\
Required flags:
{{.Context.Flags|RequiredFlags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if  .Context.Flags|OptionalFlags}}\
Optional flags:
{{.Context.Flags|OptionalFlags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
Subcommands:
{{if .Context.SelectedCommand.Commands}}\
{{template "FormatCommands" .Context.SelectedCommand}}
{{end}}\
{{else if .App.Commands}}\
Commands:
{{template "FormatCommands" .App}}
{{end}}\
`

// Usage template with compactly formatted commands.
var CompactUsageTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommandList"}}\
{{range .}}\
{{if not .Hidden}}\
{{.Depth|Indent}}{{.Name}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
{{end}}\
{{template "FormatCommandList" .Commands}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\

{{if .Context.SelectedCommand}}\
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
{{else}}\
usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end}}\
{{if .Context.Flags}}\
Flags:
{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.SelectedCommand}}\
{{if .Context.SelectedCommand.Commands}}\
Commands:
  {{.Context.SelectedCommand}}
{{template "FormatCommandList" .Context.SelectedCommand.Commands}}
{{end}}\
{{else if .App.Commands}}\
Commands:
{{template "FormatCommandList" .App.Commands}}
{{end}}\
`

var ManPageTemplate = `{{define "FormatFlags"}}\
{{range .Flags}}\
{{if not .Hidden}}\
.TP
\fB{{if .Short}}-{{.Short|Char}}, {{end}}--{{.Name}}{{if not .IsBoolFlag}}={{.FormatPlaceHolder}}{{end}}\\fR
{{.Help}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
.SS
\fB{{.FullCommand}}{{template "FormatCommand" .}}\\fR
.PP
{{.Help}}
{{template "FormatFlags" .}}\
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}\\fR
{{end}}\

.TH {{.App.Name}} 1 {{.App.Version}} "{{.App.Author}}"
.SH "NAME"
{{.App.Name}}
.SH "SYNOPSIS"
.TP
\fB{{.App.Name}}{{template "FormatUsage" .App}}
.SH "DESCRIPTION"
{{.App.Help}}
.SH "OPTIONS"
{{template "FormatFlags" .App}}\
{{if .App.Commands}}\
.SH "COMMANDS"
{{template "FormatCommands" .App}}\
{{end}}\
`

// Default usage template.
var LongHelpTemplate = `{{define "FormatCommand"}}\
{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
{{range .Args}}{{if not .Hidden}} {{if not .Required}}[{{end}}{{if .PlaceHolder}}{{.PlaceHolder}}{{else}}<{{.Name}}>{{end}}{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}{{end}}\
{{end}}\

{{define "FormatCommands"}}\
{{range .FlattenedCommands}}\
{{if not .Hidden}}\
  {{.FullCommand}}{{template "FormatCommand" .}}
{{.Help|Wrap 4}}
{{with .Flags|FlagsToTwoColumns}}{{FormatTwoColumnsWithIndent . 4 2}}{{end}}
{{end}}\
{{end}}\
{{end}}\

{{define "FormatUsage"}}\
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0}}\
{{end}}\

{{end}}\

usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{if .Context.Flags}}\
Flags:
{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .Context.Args}}\
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end}}\
{{if .App.Commands}}\
Commands:
{{template "FormatCommands" .App}}
{{end}}\
`

var BashCompletionTemplate = `
_{{.App.Name}}_bash_autocomplete() {
    local cur prev opts base
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    opts=$( ${COMP_WORDS[0]} --completion-bash "${COMP_WORDS[@]:1:$COMP_CWORD}" )
    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
    return 0
}
complete -F _{{.App.Name}}_bash_autocomplete -o default {{.App.Name}}

`

var ZshCompletionTemplate = `#compdef {{.App.Name}}

_{{.App.Name}}() {
    local matches=($(${words[1]} --completion-bash "${(@)words[1,$CURRENT]}"))
    compadd -a matches

    if [[ $compstate[nmatches] -eq 0 && $words[$CURRENT] != -* ]]; then
        _files
    fi
}

if [[ "$(basename -- ${(%):-%x})" != "_{{.App.Name}}" ]]; then
    compdef _{{.App.Name}} {{.App.Name}}
fi
`
<|endoftext|>