Godeps, vendor: convert dependency management to trash

This commit is contained in:
Péter Szilágyi 2016-10-24 13:13:00 +03:00
parent 890ffa05f8
commit d4336f00a6
No known key found for this signature in database
GPG key ID: 119A76381CCB7DD2
875 changed files with 23105 additions and 26356 deletions

332
Godeps/Godeps.json generated
View file

@ -1,332 +0,0 @@
{
"ImportPath": "github.com/ethereum/go-ethereum",
"GoVersion": "go1.7",
"GodepVersion": "v74",
"Packages": [
"./..."
],
"Deps": [
{
"ImportPath": "github.com/Gustav-Simonsson/go-opencl/cl",
"Rev": "593e01cfc4f3353585015321e01951d4a907d3ef"
},
{
"ImportPath": "github.com/cespare/cp",
"Rev": "165db2f241fd235aec29ba6d9b1ccd5f1c14637c"
},
{
"ImportPath": "github.com/davecgh/go-spew/spew",
"Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d"
},
{
"ImportPath": "github.com/ethereum/ethash",
"Comment": "v23.1-247-g2e80de5",
"Rev": "2e80de5022370cfe632195b1720db52d07ff8a77"
},
{
"ImportPath": "github.com/fatih/color",
"Comment": "v0.1-12-g9aae6aa",
"Rev": "9aae6aaa22315390f03959adca2c4d395b02fcef"
},
{
"ImportPath": "github.com/gizak/termui",
"Rev": "08a5d3f67b7d9ec87830ea39c48e570a1f18531f"
},
{
"ImportPath": "github.com/golang/snappy",
"Rev": "799c780093d646c1b79d30894e22512c319fa137"
},
{
"ImportPath": "github.com/hashicorp/golang-lru",
"Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4"
},
{
"ImportPath": "github.com/hashicorp/golang-lru/simplelru",
"Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4"
},
{
"ImportPath": "github.com/huin/goupnp",
"Rev": "46bde78b11f3f021f2a511df138be9e2fc7506e8"
},
{
"ImportPath": "github.com/huin/goupnp/dcps/internetgateway1",
"Rev": "46bde78b11f3f021f2a511df138be9e2fc7506e8"
},
{
"ImportPath": "github.com/huin/goupnp/dcps/internetgateway2",
"Rev": "46bde78b11f3f021f2a511df138be9e2fc7506e8"
},
{
"ImportPath": "github.com/huin/goupnp/httpu",
"Rev": "46bde78b11f3f021f2a511df138be9e2fc7506e8"
},
{
"ImportPath": "github.com/huin/goupnp/scpd",
"Rev": "46bde78b11f3f021f2a511df138be9e2fc7506e8"
},
{
"ImportPath": "github.com/huin/goupnp/soap",
"Rev": "46bde78b11f3f021f2a511df138be9e2fc7506e8"
},
{
"ImportPath": "github.com/huin/goupnp/ssdp",
"Rev": "46bde78b11f3f021f2a511df138be9e2fc7506e8"
},
{
"ImportPath": "github.com/jackpal/gateway",
"Rev": "192609c58b8985e645cbe82ddcb28a4362ca0fdc"
},
{
"ImportPath": "github.com/jackpal/go-nat-pmp",
"Rev": "46523a463303c6ede3ddfe45bde1c7ed52ebaacd"
},
{
"ImportPath": "github.com/mattn/go-colorable",
"Rev": "9fdad7c47650b7d2e1da50644c1f4ba7f172f252"
},
{
"ImportPath": "github.com/mattn/go-isatty",
"Rev": "56b76bdf51f7708750eac80fa38b952bb9f32639"
},
{
"ImportPath": "github.com/mattn/go-runewidth",
"Comment": "travisish-44-ge882a96",
"Rev": "e882a96ec18dd43fa283187b66af74497c9101c0"
},
{
"ImportPath": "github.com/nsf/termbox-go",
"Rev": "362329b0aa6447eadd52edd8d660ec1dff470295"
},
{
"ImportPath": "github.com/pborman/uuid",
"Comment": "v1.0-6-g0f1a469",
"Rev": "0f1a46960a86dcdf5dd30d3e6568a497a997909f"
},
{
"ImportPath": "github.com/peterh/liner",
"Rev": "ad1edfd30321d8f006ccf05f1e0524adeb943060"
},
{
"ImportPath": "github.com/rcrowley/go-metrics",
"Rev": "51425a2415d21afadfd55cd93432c0bc69e9598d"
},
{
"ImportPath": "github.com/rcrowley/go-metrics/exp",
"Rev": "51425a2415d21afadfd55cd93432c0bc69e9598d"
},
{
"ImportPath": "github.com/rjeczalik/notify",
"Rev": "f627deca7a510d96f0ef9388f2d0e8b16d21f87f"
},
{
"ImportPath": "github.com/robertkrimen/otto",
"Rev": "53221230c215611a90762720c9042ac782ef74ee"
},
{
"ImportPath": "github.com/robertkrimen/otto/ast",
"Rev": "53221230c215611a90762720c9042ac782ef74ee"
},
{
"ImportPath": "github.com/robertkrimen/otto/dbg",
"Rev": "53221230c215611a90762720c9042ac782ef74ee"
},
{
"ImportPath": "github.com/robertkrimen/otto/file",
"Rev": "53221230c215611a90762720c9042ac782ef74ee"
},
{
"ImportPath": "github.com/robertkrimen/otto/parser",
"Rev": "53221230c215611a90762720c9042ac782ef74ee"
},
{
"ImportPath": "github.com/robertkrimen/otto/registry",
"Rev": "53221230c215611a90762720c9042ac782ef74ee"
},
{
"ImportPath": "github.com/robertkrimen/otto/token",
"Rev": "53221230c215611a90762720c9042ac782ef74ee"
},
{
"ImportPath": "github.com/rs/cors",
"Rev": "5950cf11d77f8a61b432a25dd4d444b4ced01379"
},
{
"ImportPath": "github.com/rs/xhandler",
"Rev": "d9d9599b6aaf6a058cb7b1f48291ded2cbd13390"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/cache",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/comparer",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/errors",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/filter",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/iterator",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/journal",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/memdb",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/opt",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/storage",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/table",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "github.com/syndtr/goleveldb/leveldb/util",
"Rev": "6b4daa5362b502898ddf367c5c11deb9e7a5c727"
},
{
"ImportPath": "golang.org/x/crypto/pbkdf2",
"Rev": "351dc6a5bf92a5f2ae22fadeee08eb6a45aa2d93"
},
{
"ImportPath": "golang.org/x/crypto/ripemd160",
"Rev": "351dc6a5bf92a5f2ae22fadeee08eb6a45aa2d93"
},
{
"ImportPath": "golang.org/x/crypto/scrypt",
"Rev": "351dc6a5bf92a5f2ae22fadeee08eb6a45aa2d93"
},
{
"ImportPath": "golang.org/x/net/context",
"Rev": "6250b412798208e6c90b03b7c4f226de5aa299e2"
},
{
"ImportPath": "golang.org/x/net/html",
"Rev": "6250b412798208e6c90b03b7c4f226de5aa299e2"
},
{
"ImportPath": "golang.org/x/net/html/atom",
"Rev": "6250b412798208e6c90b03b7c4f226de5aa299e2"
},
{
"ImportPath": "golang.org/x/net/html/charset",
"Rev": "6250b412798208e6c90b03b7c4f226de5aa299e2"
},
{
"ImportPath": "golang.org/x/net/websocket",
"Rev": "6250b412798208e6c90b03b7c4f226de5aa299e2"
},
{
"ImportPath": "golang.org/x/sys/unix",
"Rev": "a646d33e2ee3172a661fc09bca23bb4889a41bc8"
},
{
"ImportPath": "golang.org/x/text/encoding",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/charmap",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/htmlindex",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/internal",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/internal/identifier",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/japanese",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/korean",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/simplifiedchinese",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/traditionalchinese",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/encoding/unicode",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/internal/tag",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/internal/utf8internal",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/language",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/runes",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/text/transform",
"Rev": "d69c40b4be55797923cec7457fac7a244d91a9b6"
},
{
"ImportPath": "golang.org/x/tools/go/ast/astutil",
"Rev": "9deed8c6c1c89e0b6d68d727f215de8e851d1064"
},
{
"ImportPath": "golang.org/x/tools/imports",
"Rev": "9deed8c6c1c89e0b6d68d727f215de8e851d1064"
},
{
"ImportPath": "gopkg.in/check.v1",
"Rev": "4f90aeace3a26ad7021961c297b22c42160c7b25"
},
{
"ImportPath": "gopkg.in/fatih/set.v0",
"Comment": "v0.1.0-3-g27c4092",
"Rev": "27c40922c40b43fe04554d8223a402af3ea333f3"
},
{
"ImportPath": "gopkg.in/karalabe/cookiejar.v2/collections/prque",
"Rev": "8dcd6a7f4951f6ff3ee9cbb919a06d8925822e57"
},
{
"ImportPath": "gopkg.in/natefinch/npipe.v2",
"Rev": "c1b8fa8bdccecb0b8db834ee0b92fdbcfa606dd6"
},
{
"ImportPath": "gopkg.in/urfave/cli.v1",
"Comment": "v1.17.0",
"Rev": "01857ac33766ce0c93856370626f9799281c14f4"
}
]
}

5
Godeps/Readme generated
View file

@ -1,5 +0,0 @@
This directory tree is generated automatically by godep.
Please do not edit.
See https://github.com/tools/godep for more information.

2
Godeps/_workspace/.gitignore generated vendored
View file

@ -1,2 +0,0 @@
/pkg
/bin

View file

@ -1,3 +0,0 @@
language: go
go: 1.3

View file

@ -1,117 +0,0 @@
// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
package debug
import (
"fmt"
"net/http"
"golang.org/x/net/websocket"
)
type Server struct {
Port string
Addr string
Path string
Msg chan string
chs []chan string
}
type Client struct {
Port string
Addr string
Path string
ws *websocket.Conn
}
var defaultPort = ":8080"
func NewServer() *Server {
return &Server{
Port: defaultPort,
Addr: "localhost",
Path: "/echo",
Msg: make(chan string),
chs: make([]chan string, 0),
}
}
func NewClient() Client {
return Client{
Port: defaultPort,
Addr: "localhost",
Path: "/echo",
}
}
func (c Client) ConnectAndListen() error {
ws, err := websocket.Dial("ws://"+c.Addr+c.Port+c.Path, "", "http://"+c.Addr)
if err != nil {
return err
}
defer ws.Close()
var m string
for {
err := websocket.Message.Receive(ws, &m)
if err != nil {
fmt.Print(err)
return err
}
fmt.Print(m)
}
}
func (s *Server) ListenAndServe() error {
http.Handle(s.Path, websocket.Handler(func(ws *websocket.Conn) {
defer ws.Close()
mc := make(chan string)
s.chs = append(s.chs, mc)
for m := range mc {
websocket.Message.Send(ws, m)
}
}))
go func() {
for msg := range s.Msg {
for _, c := range s.chs {
go func(a chan string) {
a <- msg
}(c)
}
}
}()
return http.ListenAndServe(s.Port, nil)
}
func (s *Server) Log(msg string) {
go func() { s.Msg <- msg }()
}
func (s *Server) Logf(format string, a ...interface{}) {
s.Log(fmt.Sprintf(format, a...))
}
var DefaultServer = NewServer()
var DefaultClient = NewClient()
func ListenAndServe() error {
return DefaultServer.ListenAndServe()
}
func ConnectAndListen() error {
return DefaultClient.ConnectAndListen()
}
func Log(msg string) {
DefaultServer.Log(msg)
}
func Logf(format string, a ...interface{}) {
DefaultServer.Logf(format, a...)
}

View file

@ -1,66 +0,0 @@
// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
package main
import (
"fmt"
"os"
"github.com/gizak/termui"
"github.com/gizak/termui/debug"
)
func main() {
// run as client
if len(os.Args) > 1 {
fmt.Print(debug.ConnectAndListen())
return
}
// run as server
go func() { panic(debug.ListenAndServe()) }()
if err := termui.Init(); err != nil {
panic(err)
}
defer termui.Close()
//termui.UseTheme("helloworld")
b := termui.NewBlock()
b.Width = 20
b.Height = 20
b.Float = termui.AlignCenter
b.BorderLabel = "[HELLO](fg-red,bg-white) [WORLD](fg-blue,bg-green)"
termui.Render(b)
termui.Handle("/sys", func(e termui.Event) {
k, ok := e.Data.(termui.EvtKbd)
debug.Logf("->%v\n", e)
if ok && k.KeyStr == "q" {
termui.StopLoop()
}
})
termui.Handle(("/usr"), func(e termui.Event) {
debug.Logf("->%v\n", e)
})
termui.Handle("/timer/1s", func(e termui.Event) {
t := e.Data.(termui.EvtTimer)
termui.SendCustomEvt("/usr/t", t.Count)
if t.Count%2 == 0 {
b.BorderLabel = "[HELLO](fg-red,bg-green) [WORLD](fg-blue,bg-white)"
} else {
b.BorderLabel = "[HELLO](fg-blue,bg-white) [WORLD](fg-red,bg-green)"
}
termui.Render(b)
})
termui.Loop()
}

View file

@ -1,7 +0,0 @@
The Snappy compression format in the Go programming language.
To download and install from source:
$ go get github.com/golang/snappy
Unless otherwise noted, the Snappy-Go source files are distributed
under the BSD-style license found in the LICENSE file.

View file

@ -1,20 +0,0 @@
package main
import (
"log"
"net/http"
"github.com/huin/goupnp/httpu"
)
func main() {
srv := httpu.Server{
Addr: "239.255.255.250:1900",
Multicast: true,
Handler: httpu.HandlerFunc(func(r *http.Request) {
log.Printf("Got %s %s message from %v: %v", r.Method, r.URL.Path, r.RemoteAddr, r.Header)
}),
}
err := srv.ListenAndServe()
log.Printf("Serving failed with error: %v", err)
}

View file

@ -1,67 +0,0 @@
package main
import (
"fmt"
"log"
"github.com/huin/goupnp/dcps/internetgateway1"
)
func main() {
clients, errors, err := internetgateway1.NewWANPPPConnection1Clients()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Got %d errors finding servers and %d successfully discovered.\n",
len(errors), len(clients))
for i, e := range errors {
fmt.Printf("Error finding server #%d: %v\n", i+1, e)
}
for _, c := range clients {
dev := &c.ServiceClient.RootDevice.Device
srv := c.ServiceClient.Service
fmt.Println(dev.FriendlyName, " :: ", srv.String())
scpd, err := srv.RequestSCDP()
if err != nil {
fmt.Printf(" Error requesting service SCPD: %v\n", err)
} else {
fmt.Println(" Available actions:")
for _, action := range scpd.Actions {
fmt.Printf(" * %s\n", action.Name)
for _, arg := range action.Arguments {
var varDesc string
if stateVar := scpd.GetStateVariable(arg.RelatedStateVariable); stateVar != nil {
varDesc = fmt.Sprintf(" (%s)", stateVar.DataType.Name)
}
fmt.Printf(" * [%s] %s%s\n", arg.Direction, arg.Name, varDesc)
}
}
}
if scpd == nil || scpd.GetAction("GetExternalIPAddress") != nil {
ip, err := c.GetExternalIPAddress()
fmt.Println("GetExternalIPAddress: ", ip, err)
}
if scpd == nil || scpd.GetAction("GetStatusInfo") != nil {
status, lastErr, uptime, err := c.GetStatusInfo()
fmt.Println("GetStatusInfo: ", status, lastErr, uptime, err)
}
if scpd == nil || scpd.GetAction("GetIdleDisconnectTime") != nil {
idleTime, err := c.GetIdleDisconnectTime()
fmt.Println("GetIdleDisconnectTime: ", idleTime, err)
}
if scpd == nil || scpd.GetAction("AddPortMapping") != nil {
err := c.AddPortMapping("", 5000, "TCP", 5001, "192.168.1.2", true, "Test port mapping", 0)
fmt.Println("AddPortMapping: ", err)
}
if scpd == nil || scpd.GetAction("DeletePortMapping") != nil {
err := c.DeletePortMapping("", 5000, "TCP")
fmt.Println("DeletePortMapping: ", err)
}
}
}

View file

@ -1,27 +0,0 @@
package main
import (
"log"
"github.com/huin/goupnp/ssdp"
)
func main() {
c := make(chan ssdp.Update)
srv, reg := ssdp.NewServerAndRegistry()
reg.AddListener(c)
go listener(c)
if err := srv.ListenAndServe(); err != nil {
log.Print("ListenAndServe failed: ", err)
}
}
func listener(c <-chan ssdp.Update) {
for u := range c {
if u.Entry != nil {
log.Printf("Event: %v USN: %s Entry: %#v", u.EventType, u.USN, *u.Entry)
} else {
log.Printf("Event: %v USN: %s Entry: <nil>", u.EventType, u.USN)
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
// Serves as examples of using the goupnp library.
//
// To run examples and see the output for your local network, run the following
// command (specifically including the -v flag):
// go test -v github.com/huin/goupnp/example
package example

View file

@ -1,603 +0,0 @@
// +build gotask
package gotasks
import (
"archive/zip"
"encoding/xml"
"fmt"
"io"
"log"
"net/http"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
"github.com/huin/goupnp"
"github.com/huin/goupnp/scpd"
"github.com/huin/goutil/codegen"
"github.com/jingweno/gotask/tasking"
)
var (
deviceURNPrefix = "urn:schemas-upnp-org:device:"
serviceURNPrefix = "urn:schemas-upnp-org:service:"
)
// DCP contains extra metadata to use when generating DCP source files.
type DCPMetadata struct {
Name string // What to name the Go DCP package.
OfficialName string // Official name for the DCP.
DocURL string // Optional - URL for futher documentation about the DCP.
XMLSpecURL string // Where to download the XML spec from.
// Any special-case functions to run against the DCP before writing it out.
Hacks []DCPHackFn
}
var dcpMetadata = []DCPMetadata{
{
Name: "internetgateway1",
OfficialName: "Internet Gateway Device v1",
DocURL: "http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v1-Device.pdf",
XMLSpecURL: "http://upnp.org/specs/gw/UPnP-gw-IGD-TestFiles-20010921.zip",
},
{
Name: "internetgateway2",
OfficialName: "Internet Gateway Device v2",
DocURL: "http://upnp.org/specs/gw/UPnP-gw-InternetGatewayDevice-v2-Device.pdf",
XMLSpecURL: "http://upnp.org/specs/gw/UPnP-gw-IGD-Testfiles-20110224.zip",
Hacks: []DCPHackFn{
func(dcp *DCP) error {
missingURN := "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"
if _, ok := dcp.ServiceTypes[missingURN]; ok {
return nil
}
urnParts, err := extractURNParts(missingURN, serviceURNPrefix)
if err != nil {
return err
}
dcp.ServiceTypes[missingURN] = urnParts
return nil
},
},
},
{
Name: "av1",
OfficialName: "MediaServer v1 and MediaRenderer v1",
DocURL: "http://upnp.org/specs/av/av1/",
XMLSpecURL: "http://upnp.org/specs/av/UPnP-av-TestFiles-20070927.zip",
},
}
type DCPHackFn func(*DCP) error
// NAME
// specgen - generates Go code from the UPnP specification files.
//
// DESCRIPTION
// The specification is available for download from:
//
// OPTIONS
// -s, --specs_dir=<spec directory>
// Path to the specification storage directory. This is used to find (and download if not present) the specification ZIP files. Defaults to 'specs'
// -o, --out_dir=<output directory>
// Path to the output directory. This is is where the DCP source files will be placed. Should normally correspond to the directory for github.com/huin/goupnp/dcps. Defaults to '../dcps'
// --nogofmt
// Disable passing the output through gofmt. Do this if debugging code output problems and needing to see the generated code prior to being passed through gofmt.
func TaskSpecgen(t *tasking.T) {
specsDir := fallbackStrValue("specs", t.Flags.String("specs_dir"), t.Flags.String("s"))
if err := os.MkdirAll(specsDir, os.ModePerm); err != nil {
t.Fatalf("Could not create specs-dir %q: %v\n", specsDir, err)
}
outDir := fallbackStrValue("../dcps", t.Flags.String("out_dir"), t.Flags.String("o"))
useGofmt := !t.Flags.Bool("nogofmt")
NEXT_DCP:
for _, d := range dcpMetadata {
specFilename := filepath.Join(specsDir, d.Name+".zip")
err := acquireFile(specFilename, d.XMLSpecURL)
if err != nil {
t.Logf("Could not acquire spec for %s, skipping: %v\n", d.Name, err)
continue NEXT_DCP
}
dcp := newDCP(d)
if err := dcp.processZipFile(specFilename); err != nil {
log.Printf("Error processing spec for %s in file %q: %v", d.Name, specFilename, err)
continue NEXT_DCP
}
for i, hack := range d.Hacks {
if err := hack(dcp); err != nil {
log.Printf("Error with Hack[%d] for %s: %v", i, d.Name, err)
continue NEXT_DCP
}
}
dcp.writePackage(outDir, useGofmt)
if err := dcp.writePackage(outDir, useGofmt); err != nil {
log.Printf("Error writing package %q: %v", dcp.Metadata.Name, err)
continue NEXT_DCP
}
}
}
func fallbackStrValue(defaultValue string, values ...string) string {
for _, v := range values {
if v != "" {
return v
}
}
return defaultValue
}
func acquireFile(specFilename string, xmlSpecURL string) error {
if f, err := os.Open(specFilename); err != nil {
if !os.IsNotExist(err) {
return err
}
} else {
f.Close()
return nil
}
resp, err := http.Get(xmlSpecURL)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("could not download spec %q from %q: ",
specFilename, xmlSpecURL, resp.Status)
}
tmpFilename := specFilename + ".download"
w, err := os.Create(tmpFilename)
if err != nil {
return err
}
defer w.Close()
_, err = io.Copy(w, resp.Body)
if err != nil {
return err
}
return os.Rename(tmpFilename, specFilename)
}
// DCP collects together information about a UPnP Device Control Protocol.
type DCP struct {
Metadata DCPMetadata
DeviceTypes map[string]*URNParts
ServiceTypes map[string]*URNParts
Services []SCPDWithURN
}
func newDCP(metadata DCPMetadata) *DCP {
return &DCP{
Metadata: metadata,
DeviceTypes: make(map[string]*URNParts),
ServiceTypes: make(map[string]*URNParts),
}
}
func (dcp *DCP) processZipFile(filename string) error {
archive, err := zip.OpenReader(filename)
if err != nil {
return fmt.Errorf("error reading zip file %q: %v", filename, err)
}
defer archive.Close()
for _, deviceFile := range globFiles("*/device/*.xml", archive) {
if err := dcp.processDeviceFile(deviceFile); err != nil {
return err
}
}
for _, scpdFile := range globFiles("*/service/*.xml", archive) {
if err := dcp.processSCPDFile(scpdFile); err != nil {
return err
}
}
return nil
}
func (dcp *DCP) processDeviceFile(file *zip.File) error {
var device goupnp.Device
if err := unmarshalXmlFile(file, &device); err != nil {
return fmt.Errorf("error decoding device XML from file %q: %v", file.Name, err)
}
var mainErr error
device.VisitDevices(func(d *goupnp.Device) {
t := strings.TrimSpace(d.DeviceType)
if t != "" {
u, err := extractURNParts(t, deviceURNPrefix)
if err != nil {
mainErr = err
}
dcp.DeviceTypes[t] = u
}
})
device.VisitServices(func(s *goupnp.Service) {
u, err := extractURNParts(s.ServiceType, serviceURNPrefix)
if err != nil {
mainErr = err
}
dcp.ServiceTypes[s.ServiceType] = u
})
return mainErr
}
func (dcp *DCP) writePackage(outDir string, useGofmt bool) error {
packageDirname := filepath.Join(outDir, dcp.Metadata.Name)
err := os.MkdirAll(packageDirname, os.ModePerm)
if err != nil && !os.IsExist(err) {
return err
}
packageFilename := filepath.Join(packageDirname, dcp.Metadata.Name+".go")
packageFile, err := os.Create(packageFilename)
if err != nil {
return err
}
var output io.WriteCloser = packageFile
if useGofmt {
if output, err = codegen.NewGofmtWriteCloser(output); err != nil {
packageFile.Close()
return err
}
}
if err = packageTmpl.Execute(output, dcp); err != nil {
output.Close()
return err
}
return output.Close()
}
func (dcp *DCP) processSCPDFile(file *zip.File) error {
scpd := new(scpd.SCPD)
if err := unmarshalXmlFile(file, scpd); err != nil {
return fmt.Errorf("error decoding SCPD XML from file %q: %v", file.Name, err)
}
scpd.Clean()
urnParts, err := urnPartsFromSCPDFilename(file.Name)
if err != nil {
return fmt.Errorf("could not recognize SCPD filename %q: %v", file.Name, err)
}
dcp.Services = append(dcp.Services, SCPDWithURN{
URNParts: urnParts,
SCPD: scpd,
})
return nil
}
type SCPDWithURN struct {
*URNParts
SCPD *scpd.SCPD
}
func (s *SCPDWithURN) WrapArguments(args []*scpd.Argument) (argumentWrapperList, error) {
wrappedArgs := make(argumentWrapperList, len(args))
for i, arg := range args {
wa, err := s.wrapArgument(arg)
if err != nil {
return nil, err
}
wrappedArgs[i] = wa
}
return wrappedArgs, nil
}
func (s *SCPDWithURN) wrapArgument(arg *scpd.Argument) (*argumentWrapper, error) {
relVar := s.SCPD.GetStateVariable(arg.RelatedStateVariable)
if relVar == nil {
return nil, fmt.Errorf("no such state variable: %q, for argument %q", arg.RelatedStateVariable, arg.Name)
}
cnv, ok := typeConvs[relVar.DataType.Name]
if !ok {
return nil, fmt.Errorf("unknown data type: %q, for state variable %q, for argument %q", relVar.DataType.Type, arg.RelatedStateVariable, arg.Name)
}
return &argumentWrapper{
Argument: *arg,
relVar: relVar,
conv: cnv,
}, nil
}
type argumentWrapper struct {
scpd.Argument
relVar *scpd.StateVariable
conv conv
}
func (arg *argumentWrapper) AsParameter() string {
return fmt.Sprintf("%s %s", arg.Name, arg.conv.ExtType)
}
func (arg *argumentWrapper) HasDoc() bool {
rng := arg.relVar.AllowedValueRange
return ((rng != nil && (rng.Minimum != "" || rng.Maximum != "" || rng.Step != "")) ||
len(arg.relVar.AllowedValues) > 0)
}
func (arg *argumentWrapper) Document() string {
relVar := arg.relVar
if rng := relVar.AllowedValueRange; rng != nil {
var parts []string
if rng.Minimum != "" {
parts = append(parts, fmt.Sprintf("minimum=%s", rng.Minimum))
}
if rng.Maximum != "" {
parts = append(parts, fmt.Sprintf("maximum=%s", rng.Maximum))
}
if rng.Step != "" {
parts = append(parts, fmt.Sprintf("step=%s", rng.Step))
}
return "allowed value range: " + strings.Join(parts, ", ")
}
if len(relVar.AllowedValues) != 0 {
return "allowed values: " + strings.Join(relVar.AllowedValues, ", ")
}
return ""
}
func (arg *argumentWrapper) Marshal() string {
return fmt.Sprintf("soap.Marshal%s(%s)", arg.conv.FuncSuffix, arg.Name)
}
func (arg *argumentWrapper) Unmarshal(objVar string) string {
return fmt.Sprintf("soap.Unmarshal%s(%s.%s)", arg.conv.FuncSuffix, objVar, arg.Name)
}
type argumentWrapperList []*argumentWrapper
func (args argumentWrapperList) HasDoc() bool {
for _, arg := range args {
if arg.HasDoc() {
return true
}
}
return false
}
type conv struct {
FuncSuffix string
ExtType string
}
// typeConvs maps from a SOAP type (e.g "fixed.14.4") to the function name
// suffix inside the soap module (e.g "Fixed14_4") and the Go type.
var typeConvs = map[string]conv{
"ui1": conv{"Ui1", "uint8"},
"ui2": conv{"Ui2", "uint16"},
"ui4": conv{"Ui4", "uint32"},
"i1": conv{"I1", "int8"},
"i2": conv{"I2", "int16"},
"i4": conv{"I4", "int32"},
"int": conv{"Int", "int64"},
"r4": conv{"R4", "float32"},
"r8": conv{"R8", "float64"},
"number": conv{"R8", "float64"}, // Alias for r8.
"fixed.14.4": conv{"Fixed14_4", "float64"},
"float": conv{"R8", "float64"},
"char": conv{"Char", "rune"},
"string": conv{"String", "string"},
"date": conv{"Date", "time.Time"},
"dateTime": conv{"DateTime", "time.Time"},
"dateTime.tz": conv{"DateTimeTz", "time.Time"},
"time": conv{"TimeOfDay", "soap.TimeOfDay"},
"time.tz": conv{"TimeOfDayTz", "soap.TimeOfDay"},
"boolean": conv{"Boolean", "bool"},
"bin.base64": conv{"BinBase64", "[]byte"},
"bin.hex": conv{"BinHex", "[]byte"},
"uri": conv{"URI", "*url.URL"},
}
func globFiles(pattern string, archive *zip.ReadCloser) []*zip.File {
var files []*zip.File
for _, f := range archive.File {
if matched, err := path.Match(pattern, f.Name); err != nil {
// This shouldn't happen - all patterns are hard-coded, errors in them
// are a programming error.
panic(err)
} else if matched {
files = append(files, f)
}
}
return files
}
func unmarshalXmlFile(file *zip.File, data interface{}) error {
r, err := file.Open()
if err != nil {
return err
}
decoder := xml.NewDecoder(r)
r.Close()
return decoder.Decode(data)
}
type URNParts struct {
URN string
Name string
Version string
}
func (u *URNParts) Const() string {
return fmt.Sprintf("URN_%s_%s", u.Name, u.Version)
}
// extractURNParts extracts the name and version from a URN string.
func extractURNParts(urn, expectedPrefix string) (*URNParts, error) {
if !strings.HasPrefix(urn, expectedPrefix) {
return nil, fmt.Errorf("%q does not have expected prefix %q", urn, expectedPrefix)
}
parts := strings.SplitN(strings.TrimPrefix(urn, expectedPrefix), ":", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("%q does not have a name and version", urn)
}
name, version := parts[0], parts[1]
return &URNParts{urn, name, version}, nil
}
var scpdFilenameRe = regexp.MustCompile(
`.*/([a-zA-Z0-9]+)([0-9]+)\.xml`)
func urnPartsFromSCPDFilename(filename string) (*URNParts, error) {
parts := scpdFilenameRe.FindStringSubmatch(filename)
if len(parts) != 3 {
return nil, fmt.Errorf("SCPD filename %q does not have expected number of parts", filename)
}
name, version := parts[1], parts[2]
return &URNParts{
URN: serviceURNPrefix + name + ":" + version,
Name: name,
Version: version,
}, nil
}
var packageTmpl = template.Must(template.New("package").Parse(`{{$name := .Metadata.Name}}
// Client for UPnP Device Control Protocol {{.Metadata.OfficialName}}.
// {{if .Metadata.DocURL}}
// This DCP is documented in detail at: {{.Metadata.DocURL}}{{end}}
//
// Typically, use one of the New* functions to create clients for services.
package {{$name}}
// Generated file - do not edit by hand. See README.md
import (
"net/url"
"time"
"github.com/huin/goupnp"
"github.com/huin/goupnp/soap"
)
// Hack to avoid Go complaining if time isn't used.
var _ time.Time
// Device URNs:
const ({{range .DeviceTypes}}
{{.Const}} = "{{.URN}}"{{end}}
)
// Service URNs:
const ({{range .ServiceTypes}}
{{.Const}} = "{{.URN}}"{{end}}
)
{{range .Services}}
{{$srv := .}}
{{$srvIdent := printf "%s%s" .Name .Version}}
// {{$srvIdent}} is a client for UPnP SOAP service with URN "{{.URN}}". See
// goupnp.ServiceClient, which contains RootDevice and Service attributes which
// are provided for informational value.
type {{$srvIdent}} struct {
goupnp.ServiceClient
}
// New{{$srvIdent}}Clients discovers instances of the service on the network,
// and returns clients to any that are found. errors will contain an error for
// any devices that replied but which could not be queried, and err will be set
// if the discovery process failed outright.
//
// This is a typical entry calling point into this package.
func New{{$srvIdent}}Clients() (clients []*{{$srvIdent}}, errors []error, err error) {
var genericClients []goupnp.ServiceClient
if genericClients, errors, err = goupnp.NewServiceClients({{$srv.Const}}); err != nil {
return
}
clients = new{{$srvIdent}}ClientsFromGenericClients(genericClients)
return
}
// New{{$srvIdent}}ClientsByURL discovers instances of the service at the given
// URL, and returns clients to any that are found. An error is returned if
// there was an error probing the service.
//
// This is a typical entry calling point into this package when reusing an
// previously discovered service URL.
func New{{$srvIdent}}ClientsByURL(loc *url.URL) ([]*{{$srvIdent}}, error) {
genericClients, err := goupnp.NewServiceClientsByURL(loc, {{$srv.Const}})
if err != nil {
return nil, err
}
return new{{$srvIdent}}ClientsFromGenericClients(genericClients), nil
}
// New{{$srvIdent}}ClientsFromRootDevice discovers instances of the service in
// a given root device, and returns clients to any that are found. An error is
// returned if there was not at least one instance of the service within the
// device. The location parameter is simply assigned to the Location attribute
// of the wrapped ServiceClient(s).
//
// This is a typical entry calling point into this package when reusing an
// previously discovered root device.
func New{{$srvIdent}}ClientsFromRootDevice(rootDevice *goupnp.RootDevice, loc *url.URL) ([]*{{$srvIdent}}, error) {
genericClients, err := goupnp.NewServiceClientsFromRootDevice(rootDevice, loc, {{$srv.Const}})
if err != nil {
return nil, err
}
return new{{$srvIdent}}ClientsFromGenericClients(genericClients), nil
}
func new{{$srvIdent}}ClientsFromGenericClients(genericClients []goupnp.ServiceClient) []*{{$srvIdent}} {
clients := make([]*{{$srvIdent}}, len(genericClients))
for i := range genericClients {
clients[i] = &{{$srvIdent}}{genericClients[i]}
}
return clients
}
{{range .SCPD.Actions}}{{/* loops over *SCPDWithURN values */}}
{{$winargs := $srv.WrapArguments .InputArguments}}
{{$woutargs := $srv.WrapArguments .OutputArguments}}
{{if $winargs.HasDoc}}
//
// Arguments:{{range $winargs}}{{if .HasDoc}}
//
// * {{.Name}}: {{.Document}}{{end}}{{end}}{{end}}
{{if $woutargs.HasDoc}}
//
// Return values:{{range $woutargs}}{{if .HasDoc}}
//
// * {{.Name}}: {{.Document}}{{end}}{{end}}{{end}}
func (client *{{$srvIdent}}) {{.Name}}({{range $winargs}}{{/*
*/}}{{.AsParameter}}, {{end}}{{/*
*/}}) ({{range $woutargs}}{{/*
*/}}{{.AsParameter}}, {{end}} err error) {
// Request structure.
request := {{if $winargs}}&{{template "argstruct" $winargs}}{{"{}"}}{{else}}{{"interface{}(nil)"}}{{end}}
// BEGIN Marshal arguments into request.
{{range $winargs}}
if request.{{.Name}}, err = {{.Marshal}}; err != nil {
return
}{{end}}
// END Marshal arguments into request.
// Response structure.
response := {{if $woutargs}}&{{template "argstruct" $woutargs}}{{"{}"}}{{else}}{{"interface{}(nil)"}}{{end}}
// Perform the SOAP call.
if err = client.SOAPClient.PerformAction({{$srv.URNParts.Const}}, "{{.Name}}", request, response); err != nil {
return
}
// BEGIN Unmarshal arguments from response.
{{range $woutargs}}
if {{.Name}}, err = {{.Unmarshal "response"}}; err != nil {
return
}{{end}}
// END Unmarshal arguments from response.
return
}
{{end}}{{/* range .SCPD.Actions */}}
{{end}}{{/* range .Services */}}
{{define "argstruct"}}struct {{"{"}}{{range .}}
{{.Name}} string
{{end}}{{"}"}}{{end}}
`))

View file

@ -1,27 +0,0 @@
// Copyright (c) 2010 Jack Palevich. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,7 +0,0 @@
# gateway
A very simple library for discovering the IP address of the local LAN gateway.
Provides implementations for Linux, OS X (Darwin) and Windows.
Pull requests for other OSs happily considered!

View file

@ -1,40 +0,0 @@
package gateway
import (
"bytes"
"io/ioutil"
"net"
"os/exec"
)
func DiscoverGateway() (ip net.IP, err error) {
routeCmd := exec.Command("route", "-n", "get", "0.0.0.0")
stdOut, err := routeCmd.StdoutPipe()
if err != nil {
return
}
if err = routeCmd.Start(); err != nil {
return
}
output, err := ioutil.ReadAll(stdOut)
if err != nil {
return
}
// Darwin route out format is always like this:
// route to: default
// destination: default
// mask: default
// gateway: 192.168.1.1
outputLines := bytes.Split(output, []byte("\n"))
for _, line := range outputLines {
if bytes.Contains(line, []byte("gateway:")) {
gatewayFields := bytes.Fields(line)
ip = net.ParseIP(string(gatewayFields[1]))
break
}
}
err = routeCmd.Wait()
return
}

View file

@ -1,75 +0,0 @@
package gateway
import (
"bytes"
"io/ioutil"
"net"
"os/exec"
)
func discoverGatewayUsingIp() (ip net.IP, err error) {
routeCmd := exec.Command("ip", "route", "show")
stdOut, err := routeCmd.StdoutPipe()
if err != nil {
return
}
if err = routeCmd.Start(); err != nil {
return
}
output, err := ioutil.ReadAll(stdOut)
if err != nil {
return
}
// Linux 'ip route show' format looks like this:
// default via 192.168.178.1 dev wlp3s0 metric 303
// 192.168.178.0/24 dev wlp3s0 proto kernel scope link src 192.168.178.76 metric 303
outputLines := bytes.Split(output, []byte("\n"))
for _, line := range outputLines {
if bytes.Contains(line, []byte("default")) {
ipFields := bytes.Fields(line)
ip = net.ParseIP(string(ipFields[2]))
break
}
}
err = routeCmd.Wait()
return
}
func discoverGatewayUsingRoute() (ip net.IP, err error) {
routeCmd := exec.Command("route", "-n")
stdOut, err := routeCmd.StdoutPipe()
if err != nil {
return
}
if err = routeCmd.Start(); err != nil {
return
}
output, err := ioutil.ReadAll(stdOut)
if err != nil {
return
}
// Linux route out format is always like this:
// Kernel IP routing table
// Destination Gateway Genmask Flags Metric Ref Use Iface
// 0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0
outputLines := bytes.Split(output, []byte("\n"))
for _, line := range outputLines {
if bytes.Contains(line, []byte("0.0.0.0")) {
ipFields := bytes.Fields(line)
ip = net.ParseIP(string(ipFields[1]))
break
}
}
err = routeCmd.Wait()
return
}
func DiscoverGateway() (ip net.IP, err error) {
ip, err = discoverGatewayUsingRoute()
if err != nil {
ip, err = discoverGatewayUsingIp()
}
return
}

View file

@ -1,14 +0,0 @@
// +build !darwin,!linux,!windows
package gateway
import (
"fmt"
"net"
"runtime"
)
func DiscoverGateway() (ip net.IP, err error) {
err = fmt.Errorf("DiscoverGateway not implemented for OS %s", runtime.GOOS)
return
}

View file

@ -1,43 +0,0 @@
package gateway
import (
"bytes"
"io/ioutil"
"net"
"os/exec"
)
func DiscoverGateway() (ip net.IP, err error) {
routeCmd := exec.Command("route", "print", "0.0.0.0")
stdOut, err := routeCmd.StdoutPipe()
if err != nil {
return
}
if err = routeCmd.Start(); err != nil {
return
}
output, err := ioutil.ReadAll(stdOut)
if err != nil {
return
}
// Windows route output format is always like this:
// ===========================================================================
// Active Routes:
// Network Destination Netmask Gateway Interface Metric
// 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.100 20
// ===========================================================================
// I'm trying to pick the active route,
// then jump 2 lines and pick the third IP
// Not using regex because output is quite standard from Windows XP to 8 (NEEDS TESTING)
outputLines := bytes.Split(output, []byte("\n"))
for idx, line := range outputLines {
if bytes.Contains(line, []byte("Active Routes:")) {
ipFields := bytes.Fields(outputLines[idx+2])
ip = net.ParseIP(string(ipFields[2]))
break
}
}
err = routeCmd.Wait()
return
}

View file

@ -1,20 +0,0 @@
package main
import (
"fmt"
"github.com/rcrowley/go-metrics"
"time"
)
func main() {
r := metrics.NewRegistry()
for i := 0; i < 10000; i++ {
r.Register(fmt.Sprintf("counter-%d", i), metrics.NewCounter())
r.Register(fmt.Sprintf("gauge-%d", i), metrics.NewGauge())
r.Register(fmt.Sprintf("gaugefloat64-%d", i), metrics.NewGaugeFloat64())
r.Register(fmt.Sprintf("histogram-uniform-%d", i), metrics.NewHistogram(metrics.NewUniformSample(1028)))
r.Register(fmt.Sprintf("histogram-exp-%d", i), metrics.NewHistogram(metrics.NewExpDecaySample(1028, 0.015)))
r.Register(fmt.Sprintf("meter-%d", i), metrics.NewMeter())
}
time.Sleep(600e9)
}

View file

@ -1,154 +0,0 @@
package main
import (
"errors"
"github.com/rcrowley/go-metrics"
// "github.com/rcrowley/go-metrics/stathat"
"log"
"math/rand"
"os"
// "syslog"
"time"
)
const fanout = 10
func main() {
r := metrics.NewRegistry()
c := metrics.NewCounter()
r.Register("foo", c)
for i := 0; i < fanout; i++ {
go func() {
for {
c.Dec(19)
time.Sleep(300e6)
}
}()
go func() {
for {
c.Inc(47)
time.Sleep(400e6)
}
}()
}
g := metrics.NewGauge()
r.Register("bar", g)
for i := 0; i < fanout; i++ {
go func() {
for {
g.Update(19)
time.Sleep(300e6)
}
}()
go func() {
for {
g.Update(47)
time.Sleep(400e6)
}
}()
}
gf := metrics.NewGaugeFloat64()
r.Register("barfloat64", gf)
for i := 0; i < fanout; i++ {
go func() {
for {
g.Update(19.0)
time.Sleep(300e6)
}
}()
go func() {
for {
g.Update(47.0)
time.Sleep(400e6)
}
}()
}
hc := metrics.NewHealthcheck(func(h metrics.Healthcheck) {
if 0 < rand.Intn(2) {
h.Healthy()
} else {
h.Unhealthy(errors.New("baz"))
}
})
r.Register("baz", hc)
s := metrics.NewExpDecaySample(1028, 0.015)
//s := metrics.NewUniformSample(1028)
h := metrics.NewHistogram(s)
r.Register("bang", h)
for i := 0; i < fanout; i++ {
go func() {
for {
h.Update(19)
time.Sleep(300e6)
}
}()
go func() {
for {
h.Update(47)
time.Sleep(400e6)
}
}()
}
m := metrics.NewMeter()
r.Register("quux", m)
for i := 0; i < fanout; i++ {
go func() {
for {
m.Mark(19)
time.Sleep(300e6)
}
}()
go func() {
for {
m.Mark(47)
time.Sleep(400e6)
}
}()
}
t := metrics.NewTimer()
r.Register("hooah", t)
for i := 0; i < fanout; i++ {
go func() {
for {
t.Time(func() { time.Sleep(300e6) })
}
}()
go func() {
for {
t.Time(func() { time.Sleep(400e6) })
}
}()
}
metrics.RegisterDebugGCStats(r)
go metrics.CaptureDebugGCStats(r, 5e9)
metrics.RegisterRuntimeMemStats(r)
go metrics.CaptureRuntimeMemStats(r, 5e9)
metrics.Log(r, 60e9, log.New(os.Stderr, "metrics: ", log.Lmicroseconds))
/*
w, err := syslog.Dial("unixgram", "/dev/log", syslog.LOG_INFO, "metrics")
if nil != err { log.Fatalln(err) }
metrics.Syslog(r, 60e9, w)
*/
/*
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003")
metrics.Graphite(r, 10e9, "metrics", addr)
*/
/*
stathat.Stathat(r, 10e9, "example@example.com")
*/
}

View file

@ -1,22 +0,0 @@
package main
import (
"log"
"net"
)
func main() {
addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:2003")
l, err := net.ListenTCP("tcp", addr)
if nil != err {
log.Fatalln(err)
}
log.Println("listening", l.Addr())
for {
c, err := l.AcceptTCP()
if nil != err {
log.Fatalln(err)
}
log.Println("accepted", c.RemoteAddr())
}
}

View file

@ -1,102 +0,0 @@
package librato
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
const Operations = "operations"
const OperationsShort = "ops"
type LibratoClient struct {
Email, Token string
}
// property strings
const (
// display attributes
Color = "color"
DisplayMax = "display_max"
DisplayMin = "display_min"
DisplayUnitsLong = "display_units_long"
DisplayUnitsShort = "display_units_short"
DisplayStacked = "display_stacked"
DisplayTransform = "display_transform"
// special gauge display attributes
SummarizeFunction = "summarize_function"
Aggregate = "aggregate"
// metric keys
Name = "name"
Period = "period"
Description = "description"
DisplayName = "display_name"
Attributes = "attributes"
// measurement keys
MeasureTime = "measure_time"
Source = "source"
Value = "value"
// special gauge keys
Count = "count"
Sum = "sum"
Max = "max"
Min = "min"
SumSquares = "sum_squares"
// batch keys
Counters = "counters"
Gauges = "gauges"
MetricsPostUrl = "https://metrics-api.librato.com/v1/metrics"
)
type Measurement map[string]interface{}
type Metric map[string]interface{}
type Batch struct {
Gauges []Measurement `json:"gauges,omitempty"`
Counters []Measurement `json:"counters,omitempty"`
MeasureTime int64 `json:"measure_time"`
Source string `json:"source"`
}
func (self *LibratoClient) PostMetrics(batch Batch) (err error) {
var (
js []byte
req *http.Request
resp *http.Response
)
if len(batch.Counters) == 0 && len(batch.Gauges) == 0 {
return nil
}
if js, err = json.Marshal(batch); err != nil {
return
}
if req, err = http.NewRequest("POST", MetricsPostUrl, bytes.NewBuffer(js)); err != nil {
return
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(self.Email, self.Token)
if resp, err = http.DefaultClient.Do(req); err != nil {
return
}
if resp.StatusCode != http.StatusOK {
var body []byte
if body, err = ioutil.ReadAll(resp.Body); err != nil {
body = []byte(fmt.Sprintf("(could not fetch response body for error: %s)", err))
}
err = fmt.Errorf("Unable to post to Librato: %d %s %s", resp.StatusCode, resp.Status, string(body))
}
return
}

View file

@ -1,235 +0,0 @@
package librato
import (
"fmt"
"log"
"math"
"regexp"
"time"
"github.com/rcrowley/go-metrics"
)
// a regexp for extracting the unit from time.Duration.String
var unitRegexp = regexp.MustCompile("[^\\d]+$")
// a helper that turns a time.Duration into librato display attributes for timer metrics
func translateTimerAttributes(d time.Duration) (attrs map[string]interface{}) {
attrs = make(map[string]interface{})
attrs[DisplayTransform] = fmt.Sprintf("x/%d", int64(d))
attrs[DisplayUnitsShort] = string(unitRegexp.Find([]byte(d.String())))
return
}
type Reporter struct {
Email, Token string
Namespace string
Source string
Interval time.Duration
Registry metrics.Registry
Percentiles []float64 // percentiles to report on histogram metrics
TimerAttributes map[string]interface{} // units in which timers will be displayed
intervalSec int64
}
func NewReporter(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) *Reporter {
return &Reporter{e, t, "", s, d, r, p, translateTimerAttributes(u), int64(d / time.Second)}
}
func Librato(r metrics.Registry, d time.Duration, e string, t string, s string, p []float64, u time.Duration) {
NewReporter(r, d, e, t, s, p, u).Run()
}
func (self *Reporter) Run() {
log.Printf("WARNING: This client has been DEPRECATED! It has been moved to https://github.com/mihasya/go-metrics-librato and will be removed from rcrowley/go-metrics on August 5th 2015")
ticker := time.Tick(self.Interval)
metricsApi := &LibratoClient{self.Email, self.Token}
for now := range ticker {
var metrics Batch
var err error
if metrics, err = self.BuildRequest(now, self.Registry); err != nil {
log.Printf("ERROR constructing librato request body %s", err)
continue
}
if err := metricsApi.PostMetrics(metrics); err != nil {
log.Printf("ERROR sending metrics to librato %s", err)
continue
}
}
}
// calculate sum of squares from data provided by metrics.Histogram
// see http://en.wikipedia.org/wiki/Standard_deviation#Rapid_calculation_methods
func sumSquares(s metrics.Sample) float64 {
count := float64(s.Count())
sumSquared := math.Pow(count*s.Mean(), 2)
sumSquares := math.Pow(count*s.StdDev(), 2) + sumSquared/count
if math.IsNaN(sumSquares) {
return 0.0
}
return sumSquares
}
func sumSquaresTimer(t metrics.Timer) float64 {
count := float64(t.Count())
sumSquared := math.Pow(count*t.Mean(), 2)
sumSquares := math.Pow(count*t.StdDev(), 2) + sumSquared/count
if math.IsNaN(sumSquares) {
return 0.0
}
return sumSquares
}
func (self *Reporter) BuildRequest(now time.Time, r metrics.Registry) (snapshot Batch, err error) {
snapshot = Batch{
// coerce timestamps to a stepping fn so that they line up in Librato graphs
MeasureTime: (now.Unix() / self.intervalSec) * self.intervalSec,
Source: self.Source,
}
snapshot.Gauges = make([]Measurement, 0)
snapshot.Counters = make([]Measurement, 0)
histogramGaugeCount := 1 + len(self.Percentiles)
r.Each(func(name string, metric interface{}) {
if self.Namespace != "" {
name = fmt.Sprintf("%s.%s", self.Namespace, name)
}
measurement := Measurement{}
measurement[Period] = self.Interval.Seconds()
switch m := metric.(type) {
case metrics.Counter:
if m.Count() > 0 {
measurement[Name] = fmt.Sprintf("%s.%s", name, "count")
measurement[Value] = float64(m.Count())
measurement[Attributes] = map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
DisplayMin: "0",
}
snapshot.Counters = append(snapshot.Counters, measurement)
}
case metrics.Gauge:
measurement[Name] = name
measurement[Value] = float64(m.Value())
snapshot.Gauges = append(snapshot.Gauges, measurement)
case metrics.GaugeFloat64:
measurement[Name] = name
measurement[Value] = float64(m.Value())
snapshot.Gauges = append(snapshot.Gauges, measurement)
case metrics.Histogram:
if m.Count() > 0 {
gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
s := m.Sample()
measurement[Name] = fmt.Sprintf("%s.%s", name, "hist")
measurement[Count] = uint64(s.Count())
measurement[Max] = float64(s.Max())
measurement[Min] = float64(s.Min())
measurement[Sum] = float64(s.Sum())
measurement[SumSquares] = sumSquares(s)
gauges[0] = measurement
for i, p := range self.Percentiles {
gauges[i+1] = Measurement{
Name: fmt.Sprintf("%s.%.2f", measurement[Name], p),
Value: s.Percentile(p),
Period: measurement[Period],
}
}
snapshot.Gauges = append(snapshot.Gauges, gauges...)
}
case metrics.Meter:
measurement[Name] = name
measurement[Value] = float64(m.Count())
snapshot.Counters = append(snapshot.Counters, measurement)
snapshot.Gauges = append(snapshot.Gauges,
Measurement{
Name: fmt.Sprintf("%s.%s", name, "1min"),
Value: m.Rate1(),
Period: int64(self.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
DisplayMin: "0",
},
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "5min"),
Value: m.Rate5(),
Period: int64(self.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
DisplayMin: "0",
},
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "15min"),
Value: m.Rate15(),
Period: int64(self.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
DisplayMin: "0",
},
},
)
case metrics.Timer:
measurement[Name] = name
measurement[Value] = float64(m.Count())
snapshot.Counters = append(snapshot.Counters, measurement)
if m.Count() > 0 {
libratoName := fmt.Sprintf("%s.%s", name, "timer.mean")
gauges := make([]Measurement, histogramGaugeCount, histogramGaugeCount)
gauges[0] = Measurement{
Name: libratoName,
Count: uint64(m.Count()),
Sum: m.Mean() * float64(m.Count()),
Max: float64(m.Max()),
Min: float64(m.Min()),
SumSquares: sumSquaresTimer(m),
Period: int64(self.Interval.Seconds()),
Attributes: self.TimerAttributes,
}
for i, p := range self.Percentiles {
gauges[i+1] = Measurement{
Name: fmt.Sprintf("%s.timer.%2.0f", name, p*100),
Value: m.Percentile(p),
Period: int64(self.Interval.Seconds()),
Attributes: self.TimerAttributes,
}
}
snapshot.Gauges = append(snapshot.Gauges, gauges...)
snapshot.Gauges = append(snapshot.Gauges,
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.1min"),
Value: m.Rate1(),
Period: int64(self.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
DisplayMin: "0",
},
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.5min"),
Value: m.Rate5(),
Period: int64(self.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
DisplayMin: "0",
},
},
Measurement{
Name: fmt.Sprintf("%s.%s", name, "rate.15min"),
Value: m.Rate15(),
Period: int64(self.Interval.Seconds()),
Attributes: map[string]interface{}{
DisplayUnitsLong: Operations,
DisplayUnitsShort: OperationsShort,
DisplayMin: "0",
},
},
)
}
}
})
return
}

View file

@ -1,69 +0,0 @@
// Metrics output to StatHat.
package stathat
import (
"github.com/rcrowley/go-metrics"
"github.com/stathat/go"
"log"
"time"
)
func Stathat(r metrics.Registry, d time.Duration, userkey string) {
for {
if err := sh(r, userkey); nil != err {
log.Println(err)
}
time.Sleep(d)
}
}
func sh(r metrics.Registry, userkey string) error {
r.Each(func(name string, i interface{}) {
switch metric := i.(type) {
case metrics.Counter:
stathat.PostEZCount(name, userkey, int(metric.Count()))
case metrics.Gauge:
stathat.PostEZValue(name, userkey, float64(metric.Value()))
case metrics.GaugeFloat64:
stathat.PostEZValue(name, userkey, float64(metric.Value()))
case metrics.Histogram:
h := metric.Snapshot()
ps := h.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
stathat.PostEZCount(name+".count", userkey, int(h.Count()))
stathat.PostEZValue(name+".min", userkey, float64(h.Min()))
stathat.PostEZValue(name+".max", userkey, float64(h.Max()))
stathat.PostEZValue(name+".mean", userkey, float64(h.Mean()))
stathat.PostEZValue(name+".std-dev", userkey, float64(h.StdDev()))
stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0]))
stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1]))
stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2]))
stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3]))
stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4]))
case metrics.Meter:
m := metric.Snapshot()
stathat.PostEZCount(name+".count", userkey, int(m.Count()))
stathat.PostEZValue(name+".one-minute", userkey, float64(m.Rate1()))
stathat.PostEZValue(name+".five-minute", userkey, float64(m.Rate5()))
stathat.PostEZValue(name+".fifteen-minute", userkey, float64(m.Rate15()))
stathat.PostEZValue(name+".mean", userkey, float64(m.RateMean()))
case metrics.Timer:
t := metric.Snapshot()
ps := t.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999})
stathat.PostEZCount(name+".count", userkey, int(t.Count()))
stathat.PostEZValue(name+".min", userkey, float64(t.Min()))
stathat.PostEZValue(name+".max", userkey, float64(t.Max()))
stathat.PostEZValue(name+".mean", userkey, float64(t.Mean()))
stathat.PostEZValue(name+".std-dev", userkey, float64(t.StdDev()))
stathat.PostEZValue(name+".50-percentile", userkey, float64(ps[0]))
stathat.PostEZValue(name+".75-percentile", userkey, float64(ps[1]))
stathat.PostEZValue(name+".95-percentile", userkey, float64(ps[2]))
stathat.PostEZValue(name+".99-percentile", userkey, float64(ps[3]))
stathat.PostEZValue(name+".999-percentile", userkey, float64(ps[4]))
stathat.PostEZValue(name+".one-minute", userkey, float64(t.Rate1()))
stathat.PostEZValue(name+".five-minute", userkey, float64(t.Rate5()))
stathat.PostEZValue(name+".fifteen-minute", userkey, float64(t.Rate15()))
stathat.PostEZValue(name+".mean-rate", userkey, float64(t.RateMean()))
}
})
return nil
}

View file

@ -1,92 +0,0 @@
package ast
import (
"fmt"
"github.com/robertkrimen/otto/file"
)
// CommentPosition determines where the comment is in a given context
type CommentPosition int
const (
_ CommentPosition = iota
LEADING // Before the pertinent expression
TRAILING // After the pertinent expression
KEY // After a key or keyword
COLON // After a colon in a field declaration
FINAL // Final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal
TBD
)
// Comment contains the data of the comment
type Comment struct {
Begin file.Idx
Text string
Position CommentPosition
}
// String returns a stringified version of the position
func (cp CommentPosition) String() string {
switch cp {
case LEADING:
return "Leading"
case TRAILING:
return "Trailing"
case KEY:
return "Key"
case COLON:
return "Colon"
case FINAL:
return "Final"
default:
return "???"
}
}
// String returns a stringified version of the comment
func (c Comment) String() string {
return fmt.Sprintf("Comment: %v", c.Text)
}
// CommentMap is the data structure where all found comments are stored
type CommentMap map[Node][]*Comment
// AddComment adds a single comment to the map
func (cm CommentMap) AddComment(node Node, comment *Comment) {
list := cm[node]
list = append(list, comment)
cm[node] = list
}
// AddComments adds a slice of comments, given a node and an updated position
func (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition) {
for _, comment := range comments {
comment.Position = position
cm.AddComment(node, comment)
}
}
// Size returns the size of the map
func (cm CommentMap) Size() int {
size := 0
for _, comments := range cm {
size += len(comments)
}
return size
}
// MoveComments moves comments with a given position from a node to another
func (cm CommentMap) MoveComments(from, to Node, position CommentPosition) {
for i, c := range cm[from] {
if c.Position == position {
cm.AddComment(to, c)
// Remove the comment from the "from" slice
cm[from][i] = cm[from][len(cm[from])-1]
cm[from][len(cm[from])-1] = nil
cm[from] = cm[from][:len(cm[from])-1]
}
}
}

View file

@ -1,5 +0,0 @@
.PHONY: build
build:
go build -a
-gxc build-darwin-386 -a

View file

@ -1,48 +0,0 @@
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"github.com/robertkrimen/otto"
"github.com/robertkrimen/otto/underscore"
)
var flag_underscore *bool = flag.Bool("underscore", true, "Load underscore into the runtime environment")
func readSource(filename string) ([]byte, error) {
if filename == "" || filename == "-" {
return ioutil.ReadAll(os.Stdin)
}
return ioutil.ReadFile(filename)
}
func main() {
flag.Parse()
if !*flag_underscore {
underscore.Disable()
}
err := func() error {
src, err := readSource(flag.Arg(0))
if err != nil {
return err
}
vm := otto.New()
_, err = vm.Run(src)
return err
}()
if err != nil {
switch err := err.(type) {
case *otto.Error:
fmt.Print(err.String())
default:
fmt.Println(err)
}
os.Exit(64)
}
}

View file

@ -1,115 +0,0 @@
// Package repl implements a REPL (read-eval-print loop) for otto.
package repl
import (
"fmt"
"io"
"strings"
"sync/atomic"
"github.com/robertkrimen/otto"
"gopkg.in/readline.v1"
)
var counter uint32
// DebuggerHandler implements otto's debugger handler signature, providing a
// simple drop-in debugger implementation.
func DebuggerHandler(vm *otto.Otto) {
i := atomic.AddUint32(&counter, 1)
// purposefully ignoring the error here - we can't do anything useful with
// it except panicking, and that'd be pretty rude. it'd be easy enough for a
// consumer to define an equivalent function that _does_ panic if desired.
_ = RunWithPrompt(vm, fmt.Sprintf("DEBUGGER[%d]>", i))
}
// Run creates a REPL with the default prompt and no prelude.
func Run(vm *otto.Otto) error {
return RunWithPromptAndPrelude(vm, "", "")
}
// RunWithPrompt runs a REPL with the given prompt and no prelude.
func RunWithPrompt(vm *otto.Otto, prompt string) error {
return RunWithPromptAndPrelude(vm, prompt, "")
}
// RunWithPrelude runs a REPL with the default prompt and the given prelude.
func RunWithPrelude(vm *otto.Otto, prelude string) error {
return RunWithPromptAndPrelude(vm, "", prelude)
}
// RunWithPromptAndPrelude runs a REPL with the given prompt and prelude.
func RunWithPromptAndPrelude(vm *otto.Otto, prompt, prelude string) error {
if prompt == "" {
prompt = ">"
}
prompt = strings.Trim(prompt, " ")
prompt += " "
rl, err := readline.New(prompt)
if err != nil {
return err
}
if prelude != "" {
if _, err := io.Copy(rl.Stderr(), strings.NewReader(prelude+"\n")); err != nil {
return err
}
rl.Refresh()
}
var d []string
for {
l, err := rl.Readline()
if err != nil {
if err == readline.ErrInterrupt {
if d != nil {
d = nil
rl.SetPrompt(prompt)
rl.Refresh()
continue
}
break
}
return err
}
if l == "" {
continue
}
d = append(d, l)
s, err := vm.Compile("repl", strings.Join(d, "\n"))
if err != nil {
rl.SetPrompt(strings.Repeat(" ", len(prompt)))
} else {
rl.SetPrompt(prompt)
d = nil
v, err := vm.Eval(s)
if err != nil {
if oerr, ok := err.(*otto.Error); ok {
io.Copy(rl.Stdout(), strings.NewReader(oerr.String()))
} else {
io.Copy(rl.Stdout(), strings.NewReader(err.Error()))
}
} else {
rl.Stdout().Write([]byte(v.String() + "\n"))
}
}
rl.Refresh()
}
return rl.Close()
}

View file

@ -1,669 +0,0 @@
// This file was AUTOMATICALLY GENERATED by terst-import (smuggol) from github.com/robertkrimen/terst
/*
Package terst is a terse (terst = test + terse), easy-to-use testing library for Go.
terst is compatible with (and works via) the standard testing package: http://golang.org/pkg/testing
var is = terst.Is
func Test(t *testing.T) {
terst.Terst(t, func() {
is("abc", "abc")
is(1, ">", 0)
var abc []int
is(abc, nil)
}
}
Do not import terst directly, instead use `terst-import` to copy it into your testing environment:
https://github.com/robertkrimen/terst/tree/master/terst-import
$ go get github.com/robertkrimen/terst/terst-import
$ terst-import
*/
package terst
import (
"bytes"
"errors"
"fmt"
"math/big"
"reflect"
"regexp"
"runtime"
"strings"
"sync"
"testing"
"time"
)
// Is compares two values (got & expect) and returns true if the comparison is true,
// false otherwise. In addition, if the comparison is false, Is will report the error
// in a manner similar to testing.T.Error(...). Is also takes an optional argument,
// a comparator, that changes how the comparison is made. The following
// comparators are available:
//
// == # got == expect (default)
// != # got != expect
//
// > # got > expect (float32, uint, uint16, int, int64, ...)
// >= # got >= expect
// < # got < expect
// <= # got <= expect
//
// =~ # regexp.MustCompile(expect).Match{String}(got)
// !~ # !regexp.MustCompile(expect).Match{String}(got)
//
// Basic usage with the default comparator (==):
//
// Is(<got>, <expect>)
//
// Specifying a different comparator:
//
// Is(<got>, <comparator>, <expect>)
//
// A simple comparison:
//
// Is(2 + 2, 4)
//
// A bit trickier:
//
// Is(1, ">", 0)
// Is(2 + 2, "!=", 5)
// Is("Nothing happens.", "=~", `ing(\s+)happens\.$`)
//
// Is should only be called under a Terst(t, ...) call. For a standalone version,
// use IsErr. If no scope is found and the comparison is false, then Is will panic the error.
//
func Is(arguments ...interface{}) bool {
err := IsErr(arguments...)
if err != nil {
call := Caller()
if call == nil {
panic(err)
}
call.Error(err)
return false
}
return true
}
type (
// ErrFail indicates a comparison failure (e.g. 0 > 1).
ErrFail error
// ErrInvalid indicates an invalid comparison (e.g. bool == string).
ErrInvalid error
)
var errInvalid = errors.New("invalid")
var registry = struct {
table map[uintptr]*_scope
lock sync.RWMutex
}{
table: map[uintptr]*_scope{},
}
func registerScope(pc uintptr, scope *_scope) {
registry.lock.Lock()
defer registry.lock.Unlock()
registry.table[pc] = scope
}
func scope() *_scope {
scope, _ := findScope()
return scope
}
func floatCompare(a float64, b float64) int {
if a > b {
return 1
} else if a < b {
return -1
}
// NaN == NaN
return 0
}
func bigIntCompare(a *big.Int, b *big.Int) int {
return a.Cmp(b)
}
func bigInt(value int64) *big.Int {
return big.NewInt(value)
}
func bigUint(value uint64) *big.Int {
return big.NewInt(0).SetUint64(value)
}
type _toString interface {
String() string
}
func toString(value interface{}) (string, error) {
switch value := value.(type) {
case string:
return value, nil
case _toString:
return value.String(), nil
case error:
return value.Error(), nil
}
return "", errInvalid
}
func matchString(got string, expect *regexp.Regexp) (int, error) {
if expect.MatchString(got) {
return 0, nil
}
return -1, nil
}
func match(got []byte, expect *regexp.Regexp) (int, error) {
if expect.Match(got) {
return 0, nil
}
return -1, nil
}
func compareMatch(got, expect interface{}) (int, error) {
switch got := got.(type) {
case []byte:
switch expect := expect.(type) {
case string:
matcher, err := regexp.Compile(expect)
if err != nil {
return 0, err
}
return match(got, matcher)
case *regexp.Regexp:
return match(got, expect)
}
default:
if got, err := toString(got); err == nil {
switch expect := expect.(type) {
case string:
matcher, err := regexp.Compile(expect)
if err != nil {
return 0, err
}
return matchString(got, matcher)
case *regexp.Regexp:
return matchString(got, expect)
}
} else {
return 0, err
}
}
return 0, errInvalid
}
func floatPromote(value reflect.Value) (float64, error) {
kind := value.Kind()
if reflect.Int <= kind && kind <= reflect.Int64 {
return float64(value.Int()), nil
}
if reflect.Uint <= kind && kind <= reflect.Uint64 {
return float64(value.Uint()), nil
}
if reflect.Float32 <= kind && kind <= reflect.Float64 {
return value.Float(), nil
}
return 0, errInvalid
}
func bigIntPromote(value reflect.Value) (*big.Int, error) {
kind := value.Kind()
if reflect.Int <= kind && kind <= reflect.Int64 {
return bigInt(value.Int()), nil
}
if reflect.Uint <= kind && kind <= reflect.Uint64 {
return bigUint(value.Uint()), nil
}
return nil, errInvalid
}
func compareOther(got, expect interface{}) (int, error) {
{
switch expect.(type) {
case float32, float64:
return compareNumber(got, expect)
case uint, uint8, uint16, uint32, uint64:
return compareNumber(got, expect)
case int, int8, int16, int32, int64:
return compareNumber(got, expect)
case string:
var err error
got, err = toString(got)
if err != nil {
return 0, err
}
case nil:
got := reflect.ValueOf(got)
switch got.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface:
if got.IsNil() {
return 0, nil
}
return -1, nil
case reflect.Invalid: // reflect.Invalid: var abc interface{} = nil
return 0, nil
}
return 0, errInvalid
}
}
if reflect.ValueOf(got).Type() != reflect.ValueOf(expect).Type() {
return 0, errInvalid
}
if reflect.DeepEqual(got, expect) {
return 0, nil
}
return -1, nil
}
func compareNumber(got, expect interface{}) (int, error) {
{
got := reflect.ValueOf(got)
k0 := got.Kind()
expect := reflect.ValueOf(expect)
k1 := expect.Kind()
if reflect.Float32 <= k0 && k0 <= reflect.Float64 ||
reflect.Float32 <= k1 && k1 <= reflect.Float64 {
got, err := floatPromote(got)
if err != nil {
return 0, err
}
expect, err := floatPromote(expect)
if err != nil {
return 0, err
}
return floatCompare(got, expect), nil
} else {
got, err := bigIntPromote(got)
if err != nil {
return 0, err
}
expect, err := bigIntPromote(expect)
if err != nil {
return 0, err
}
return got.Cmp(expect), nil
}
}
return 0, errInvalid
}
// IsErr compares two values (got & expect) and returns nil if the comparison is true, an ErrFail if
// the comparison is false, or an ErrInvalid if the comparison is invalid. IsErr also
// takes an optional argument, a comparator, that changes how the comparison is made.
//
// Is & IsErr are similar but different:
//
// Is(...) // Should only be called within a Terst(...) call
// IsErr(...) // A standalone comparator, the same as Is, just without the automatic reporting
//
func IsErr(arguments ...interface{}) error {
var got, expect interface{}
comparator := "=="
switch len(arguments) {
case 0, 1:
return fmt.Errorf("invalid number of arguments to IsErr: %d", len(arguments))
case 2:
got, expect = arguments[0], arguments[1]
default:
if value, ok := arguments[1].(string); ok {
comparator = value
} else {
return fmt.Errorf("invalid comparator: %v", arguments[1])
}
got, expect = arguments[0], arguments[2]
}
var result int
var err error
switch comparator {
case "<", "<=", ">", ">=":
result, err = compareNumber(got, expect)
case "=~", "!~":
result, err = compareMatch(got, expect)
case "==", "!=":
result, err = compareOther(got, expect)
default:
return fmt.Errorf("invalid comparator: %s", comparator)
}
if err == errInvalid {
return ErrInvalid(fmt.Errorf(
"\nINVALID (%s):\n got: %v (%T)\n expected: %v (%T)",
comparator,
got, got,
expect, expect,
))
} else if err != nil {
return err
}
equality, pass := false, false
switch comparator {
case "==", "=~":
equality = true
pass = result == 0
case "!=", "!~":
equality = true
pass = result != 0
case "<":
pass = result < 0
case "<=":
pass = result <= 0
case ">":
pass = result > 0
case ">=":
pass = result >= 0
}
if !pass {
if equality {
if comparator[1] == '~' {
if value, ok := got.([]byte); ok {
return ErrFail(fmt.Errorf(
"\nFAIL (%s)\n got: %s %v%s\nexpected: %v%s",
comparator,
value, got, typeKindString(got),
expect, typeKindString(expect),
))
}
}
return ErrFail(fmt.Errorf(
"\nFAIL (%s)\n got: %v%s\nexpected: %v%s",
comparator,
got, typeKindString(got),
expect, typeKindString(expect),
))
}
return ErrFail(fmt.Errorf(
"\nFAIL (%s)\n got: %v%s\nexpected: %s %v%s",
comparator,
got, typeKindString(got),
comparator, expect, typeKindString(expect),
))
}
return nil
}
func typeKindString(value interface{}) string {
reflectValue := reflect.ValueOf(value)
kind := reflectValue.Kind().String()
result := fmt.Sprintf("%T", value)
if kind == result {
if kind == "string" {
return ""
}
return fmt.Sprintf(" (%T)", value)
}
return fmt.Sprintf(" (%T=%s)", value, kind)
}
func (scope *_scope) reset() {
scope.name = ""
scope.output = scope.output[:]
scope.start = time.Time{}
scope.duration = 0
}
// Terst creates a testing scope, where Is can be called and errors will be reported
// according to the top-level location of the comparison, and not where the Is call
// actually takes place. For example:
//
// func test(value int) {
// Is(value, 5) // <--- This failure is reported below.
// }
//
// Terst(t, func(){
//
// Is(2, ">", 3) // <--- An error is reported here.
//
// test(5) // <--- An error is reported here.
//
// })
//
func Terst(t *testing.T, arguments ...func()) {
scope := &_scope{
t: t,
}
pc, _, _, ok := runtime.Caller(1) // TODO Associate with the Test... func
if !ok {
panic("Here be dragons.")
}
_, scope.testFunc = findTestFunc()
registerScope(pc, scope)
for _, fn := range arguments {
func() {
scope.reset()
name := scope.testFunc.Name()
index := strings.LastIndex(scope.testFunc.Name(), ".")
if index >= 0 {
name = name[index+1:] + "(Terst)"
} else {
name = "(Terst)"
}
name = "(Terst)"
scope.name = name
scope.start = time.Now()
defer func() {
scope.duration = time.Now().Sub(scope.start)
if err := recover(); err != nil {
scope.t.Fail()
scope.report()
panic(err)
}
scope.report()
}()
fn()
}()
}
}
// From "testing"
func (scope *_scope) report() {
format := "~~~ %s: (Terst)\n%s"
if scope.t.Failed() {
fmt.Printf(format, "FAIL", scope.output)
} else if testing.Verbose() && len(scope.output) > 0 {
fmt.Printf(format, "PASS", scope.output)
}
}
func (scope *_scope) log(call _entry, str string) {
scope.mu.Lock()
defer scope.mu.Unlock()
scope.output = append(scope.output, decorate(call, str)...)
}
// decorate prefixes the string with the file and line of the call site
// and inserts the final newline if needed and indentation tabs for formascing.
func decorate(call _entry, s string) string {
file, line := call.File, call.Line
if call.PC > 0 {
// Truncate file name at last file name separator.
if index := strings.LastIndex(file, "/"); index >= 0 {
file = file[index+1:]
} else if index = strings.LastIndex(file, "\\"); index >= 0 {
file = file[index+1:]
}
} else {
file = "???"
line = 1
}
buf := new(bytes.Buffer)
// Every line is indented at least one tab.
buf.WriteByte('\t')
fmt.Fprintf(buf, "%s:%d: ", file, line)
lines := strings.Split(s, "\n")
if l := len(lines); l > 1 && lines[l-1] == "" {
lines = lines[:l-1]
}
for i, line := range lines {
if i > 0 {
// Second and subsequent lines are indented an extra tab.
buf.WriteString("\n\t\t")
}
buf.WriteString(line)
}
buf.WriteByte('\n')
return buf.String()
}
func findScope() (*_scope, _entry) {
registry.lock.RLock()
defer registry.lock.RUnlock()
table := registry.table
depth := 2 // Starting depth
call := _entry{}
for {
pc, _, _, ok := runtime.Caller(depth)
if !ok {
break
}
if scope, exists := table[pc]; exists {
pc, file, line, _ := runtime.Caller(depth - 3) // Terst(...) + func(){}() + fn() => ???()
call.PC = pc
call.File = file
call.Line = line
return scope, call
}
depth++
}
return nil, _entry{}
}
// Call is a reference to a line immediately under a Terst testing scope.
type Call struct {
scope *_scope
entry _entry
}
// Caller will search the stack, looking for a Terst testing scope. If a scope
// is found, then Caller returns a Call for logging errors, accessing testing.T, etc.
// If no scope is found, Caller returns nil.
func Caller() *Call {
scope, entry := findScope()
if scope == nil {
return nil
}
return &Call{
scope: scope,
entry: entry,
}
}
// TestFunc returns the *runtime.Func entry for the top-level Test...(t testing.T)
// function.
func (cl *Call) TestFunc() *runtime.Func {
return cl.scope.testFunc
}
// T returns the original testing.T passed to Terst(...)
func (cl *Call) T() *testing.T {
return cl.scope.t
}
// Log is the terst version of `testing.T.Log`
func (cl *Call) Log(arguments ...interface{}) {
cl.scope.log(cl.entry, fmt.Sprintln(arguments...))
}
// Logf is the terst version of `testing.T.Logf`
func (cl *Call) Logf(format string, arguments ...interface{}) {
cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...))
}
// Error is the terst version of `testing.T.Error`
func (cl *Call) Error(arguments ...interface{}) {
cl.scope.log(cl.entry, fmt.Sprintln(arguments...))
cl.scope.t.Fail()
}
// Errorf is the terst version of `testing.T.Errorf`
func (cl *Call) Errorf(format string, arguments ...interface{}) {
cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...))
cl.scope.t.Fail()
}
// Skip is the terst version of `testing.T.Skip`
func (cl *Call) Skip(arguments ...interface{}) {
cl.scope.log(cl.entry, fmt.Sprintln(arguments...))
cl.scope.t.SkipNow()
}
// Skipf is the terst version of `testing.T.Skipf`
func (cl *Call) Skipf(format string, arguments ...interface{}) {
cl.scope.log(cl.entry, fmt.Sprintf(format, arguments...))
cl.scope.t.SkipNow()
}
type _scope struct {
t *testing.T
testFunc *runtime.Func
name string
mu sync.RWMutex
output []byte
start time.Time
duration time.Duration
}
type _entry struct {
PC uintptr
File string
Line int
Func *runtime.Func
}
func _findFunc(match string) (_entry, *runtime.Func) {
depth := 2 // Starting depth
for {
pc, file, line, ok := runtime.Caller(depth)
if !ok {
break
}
fn := runtime.FuncForPC(pc)
name := fn.Name()
if index := strings.LastIndex(name, match); index >= 0 {
// Assume we have an instance of TestXyzzy in a _test file
return _entry{
PC: pc,
File: file,
Line: line,
Func: fn,
}, fn
}
depth++
}
return _entry{}, nil
}
func findTestFunc() (_entry, *runtime.Func) {
return _findFunc(".Test")
}
func findTerstFunc() (_entry, *runtime.Func) {
return _findFunc(".Terst")
}

View file

@ -1,26 +0,0 @@
.PHONY: test fetch clean build err report
TESTER := tester
test: $(TESTER)
for test in test-*.js; do ./$^ -test=true $$test 1>/dev/null || exit 1; done
@echo PASS
report: $(TESTER)
./$^ -report | grep -v "MT READY"
fetch: $(TESTER)
./$^ fetch
build:
go build -a -o $(TESTER)
$(TESTER): tester.go
$(MAKE) build
clean:
rm -f test-*.js
rm -f $(TESTER)
err: $(TESTER)
for test in test-*.js; do ./$^ $$test; done 2>$@

View file

@ -1,196 +0,0 @@
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"net/http"
"os"
"regexp"
"strings"
"sync"
"text/tabwriter"
"github.com/robertkrimen/otto"
"github.com/robertkrimen/otto/parser"
)
var flag_test *bool = flag.Bool("test", false, "")
var flag_report *bool = flag.Bool("report", false, "")
var match_ReferenceError_not_defined = regexp.MustCompile(`^ReferenceError: \S+ is not defined$`)
var match_lookahead = regexp.MustCompile(`Invalid regular expression: re2: Invalid \(\?[=!]\) <lookahead>`)
var match_backreference = regexp.MustCompile(`Invalid regular expression: re2: Invalid \\\d <backreference>`)
var match_TypeError_undefined = regexp.MustCompile(`^TypeError: Cannot access member '[^']+' of undefined$`)
var target = map[string]string{
"test-angular-bindonce.js": "fail", // (anonymous): Line 1:944 Unexpected token ( (and 40 more errors)
"test-jsforce.js": "fail", // (anonymous): Line 9:28329 RuneError (and 5 more errors)
"test-chaplin.js": "parse", // Error: Chaplin requires Common.js or AMD modules
"test-dropbox.js.js": "parse", // Error: dropbox.js loaded in an unsupported JavaScript environment.
"test-epitome.js": "parse", // TypeError: undefined is not a function
"test-portal.js": "parse", // TypeError
"test-reactive-coffee.js": "parse", // Dependencies are not met for reactive: _ and $ not found
"test-scriptaculous.js": "parse", // script.aculo.us requires the Prototype JavaScript framework >= 1.6.0.3
"test-waypoints.js": "parse", // TypeError: undefined is not a function
"test-webuploader.js": "parse", // Error: `jQuery` is undefined
"test-xuijs.js": "parse", // TypeError: undefined is not a function
}
// http://cdnjs.com/
// http://api.cdnjs.com/libraries
func fetch(name, location string) error {
response, err := http.Get(location)
if err != nil {
return err
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return err
}
if !strings.HasSuffix(location, ".js") {
return nil
}
filename := "test-" + name + ".js"
fmt.Println(filename, len(body))
return ioutil.WriteFile(filename, body, 0644)
}
func test(filename string) error {
script, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
if !*flag_report {
fmt.Fprintln(os.Stdout, filename, len(script))
}
parse := false
option := target[filename]
if option != "parse" {
vm := otto.New()
_, err = vm.Run(string(script))
if err != nil {
value := err.Error()
switch {
case match_ReferenceError_not_defined.MatchString(value):
case match_TypeError_undefined.MatchString(value):
case match_lookahead.MatchString(value):
case match_backreference.MatchString(value):
default:
return err
}
parse = true
}
}
if parse {
_, err = parser.ParseFile(nil, filename, string(script), parser.IgnoreRegExpErrors)
if err != nil {
return err
}
target[filename] = "parse"
}
return nil
}
func main() {
flag.Parse()
filename := ""
err := func() error {
if flag.Arg(0) == "fetch" {
response, err := http.Get("http://api.cdnjs.com/libraries")
if err != nil {
return err
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return err
}
var tmp map[string]interface{}
err = json.Unmarshal(body, &tmp)
if err != nil {
return err
}
var wg sync.WaitGroup
for _, value := range tmp["results"].([]interface{}) {
wg.Add(1)
library := value.(map[string]interface{})
go func() {
defer wg.Done()
fetch(library["name"].(string), library["latest"].(string))
}()
}
wg.Wait()
return nil
}
if *flag_report {
files, err := ioutil.ReadDir(".")
if err != nil {
return err
}
writer := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0)
fmt.Fprintln(writer, "", "\t| Status")
fmt.Fprintln(writer, "---", "\t| ---")
for _, file := range files {
filename := file.Name()
if !strings.HasPrefix(filename, "test-") {
continue
}
err := test(filename)
option := target[filename]
name := strings.TrimPrefix(strings.TrimSuffix(filename, ".js"), "test-")
if err == nil {
switch option {
case "":
fmt.Fprintln(writer, name, "\t| pass")
case "parse":
fmt.Fprintln(writer, name, "\t| pass (parse)")
case "re2":
continue
fmt.Fprintln(writer, name, "\t| unknown (re2)")
}
} else {
fmt.Fprintln(writer, name, "\t| fail")
}
}
writer.Flush()
return nil
}
filename = flag.Arg(0)
return test(filename)
}()
if err != nil {
if filename != "" {
if *flag_test && target[filename] == "fail" {
goto exit
}
fmt.Fprintf(os.Stderr, "%s: %s\n", filename, err.Error())
} else {
fmt.Fprintln(os.Stderr, err)
}
os.Exit(64)
}
exit:
}

View file

@ -1,13 +0,0 @@
package otto
func (rt *_runtime) newErrorObject(name string, message Value) *_object {
self := rt.newClassObject("Error")
if message.IsDefined() {
msg := message.string()
self.defineProperty("message", toValue_string(msg), 0111, false)
self.value = newError(rt, name, msg)
} else {
self.value = newError(rt, name)
}
return self
}

View file

@ -1,11 +0,0 @@
.PHONY: source
source: source.go
underscore.js:
curl -kL http://underscorejs.org/underscore.js > $@
source.go: underscore.js
go-bindata -f underscore -p underscore -u true < $< 2>/dev/null | grep -v '^//' | gofmt > $@
head -4 $< >> $@
mv $< ..

View file

@ -1,53 +0,0 @@
# underscore
--
import "github.com/robertkrimen/otto/underscore"
Package underscore contains the source for the JavaScript utility-belt library.
import (
_ "github.com/robertkrimen/otto/underscore"
)
// Every Otto runtime will now include underscore
http://underscorejs.org
https://github.com/documentcloud/underscore
By importing this package, you'll automatically load underscore every time you
create a new Otto runtime.
To prevent this behavior, you can do the following:
import (
"github.com/robertkrimen/otto/underscore"
)
func init() {
underscore.Disable()
}
## Usage
#### func Disable
```go
func Disable()
```
Disable underscore runtime inclusion.
#### func Enable
```go
func Enable()
```
Enable underscore runtime inclusion.
#### func Source
```go
func Source() string
```
Source returns the underscore source.
--
**godocdown** http://github.com/robertkrimen/godocdown

File diff suppressed because it is too large Load diff

View file

@ -1,84 +0,0 @@
#!/usr/bin/env perl
use strict;
use warnings;
my $underscore_test = shift @ARGV || "";
if (!-d $underscore_test) {
print <<_END_;
Usage:
testify ./underscore/test
# Should look something like:
arrays.js
chaining.js
collections.js
functions.js
index.html
objects.js
speed.js
utility.js
vendor
_END_
if ($underscore_test) {
die "!: Not a directory: $underscore_test\n"
}
exit;
}
chdir $underscore_test or die "!: $!";
my @js = <*.js>;
for my $file (@js) {
open my $fh, '<', $file or die "!: $!";
my $tests = join "", <$fh>;
my @tests = $tests =~ m/
^(\s{2}test\(.*?
^\s{2}}\);)$
/mgxs;
close $fh;
next unless @tests;
print "$file: ", scalar(@tests), "\n";
my $underscore_name = "underscore_$file";
$underscore_name =~ s/.js$//;
my $go_file = "${underscore_name}_test.go";
$go_file =~ s/.js$/.go/;
open $fh, '>', $go_file or die "!: $!";
$fh->print(<<_END_);
package otto
import (
"testing"
)
_END_
my $count = 0;
for my $test (@tests) {
$test =~ s/`([^`]+)`/<$1>/g;
my ($name) = $test =~ m/^\s*test\(['"]([^'"]+)['"]/;
$fh->print(<<_END_);
// $name
func Test_${underscore_name}_$count(t *testing.T) {
tt(t, func(){
test := underscoreTest()
test(`
$test
`)
})
}
_END_
$count++;
}
}
# test('#779 - delimeters are applied to unescaped text.', 1, function() {
# var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g});
# strictEqual(template(), '<<\nx\n>>');
# });

View file

@ -1,49 +0,0 @@
/*
Package underscore contains the source for the JavaScript utility-belt library.
import (
_ "github.com/robertkrimen/otto/underscore"
)
// Every Otto runtime will now include underscore
http://underscorejs.org
https://github.com/documentcloud/underscore
By importing this package, you'll automatically load underscore every time you create a new Otto runtime.
To prevent this behavior, you can do the following:
import (
"github.com/robertkrimen/otto/underscore"
)
func init() {
underscore.Disable()
}
*/
package underscore
import (
"github.com/robertkrimen/otto/registry"
)
var entry *registry.Entry = registry.Register(func() string {
return Source()
})
// Enable underscore runtime inclusion.
func Enable() {
entry.Enable()
}
// Disable underscore runtime inclusion.
func Disable() {
entry.Disable()
}
// Source returns the underscore source.
func Source() string {
return string(underscore())
}

View file

@ -1,308 +0,0 @@
/*
Package cors is net/http handler to handle CORS related requests
as defined by http://www.w3.org/TR/cors/
You can configure it by passing an option struct to cors.New:
c := cors.New(cors.Options{
AllowedOrigins: []string{"foo.com"},
AllowedMethods: []string{"GET", "POST", "DELETE"},
AllowCredentials: true,
})
Then insert the handler in the chain:
handler = c.Handler(handler)
See Options documentation for more options.
The resulting handler is a standard net/http handler.
*/
package cors
import (
"log"
"net/http"
"os"
"strconv"
"strings"
)
// Options is a configuration container to setup the CORS middleware.
type Options struct {
// AllowedOrigins is a list of origins a cross-domain request can be executed from.
// If the special "*" value is present in the list, all origins will be allowed.
// Default value is ["*"]
AllowedOrigins []string
// AllowedMethods is a list of methods the client is allowed to use with
// cross-domain requests. Default value is simple methods (GET and POST)
AllowedMethods []string
// AllowedHeaders is list of non simple headers the client is allowed to use with
// cross-domain requests.
// If the special "*" value is present in the list, all headers will be allowed.
// Default value is [] but "Origin" is always appended to the list.
AllowedHeaders []string
// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
// API specification
ExposedHeaders []string
// AllowCredentials indicates whether the request can include user credentials like
// cookies, HTTP authentication or client side SSL certificates.
AllowCredentials bool
// MaxAge indicates how long (in seconds) the results of a preflight request
// can be cached
MaxAge int
// Debugging flag adds additional output to debug server side CORS issues
Debug bool
// log object to use when debugging
log *log.Logger
}
type Cors struct {
// The CORS Options
options Options
}
// New creates a new Cors handler with the provided options.
func New(options Options) *Cors {
// Normalize options
// Note: for origins and methods matching, the spec requires a case-sensitive matching.
// As it may error prone, we chose to ignore the spec here.
normOptions := Options{
AllowedOrigins: convert(options.AllowedOrigins, strings.ToLower),
AllowedMethods: convert(options.AllowedMethods, strings.ToUpper),
// Origin is always appended as some browsers will always request
// for this header at preflight
AllowedHeaders: convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey),
ExposedHeaders: convert(options.ExposedHeaders, http.CanonicalHeaderKey),
AllowCredentials: options.AllowCredentials,
MaxAge: options.MaxAge,
Debug: options.Debug,
log: log.New(os.Stdout, "[cors] ", log.LstdFlags),
}
if len(normOptions.AllowedOrigins) == 0 {
// Default is all origins
normOptions.AllowedOrigins = []string{"*"}
}
if len(normOptions.AllowedHeaders) == 1 {
// Add some sensible defaults
normOptions.AllowedHeaders = []string{"Origin", "Accept", "Content-Type"}
}
if len(normOptions.AllowedMethods) == 0 {
// Default is simple methods
normOptions.AllowedMethods = []string{"GET", "POST"}
}
if normOptions.Debug {
normOptions.log.Printf("Options: %v", normOptions)
}
return &Cors{
options: normOptions,
}
}
// Default creates a new Cors handler with default options
func Default() *Cors {
return New(Options{})
}
// Handler apply the CORS specification on the request, and add relevant CORS headers
// as necessary.
func (cors *Cors) Handler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
cors.logf("Handler: Preflight request")
cors.handlePreflight(w, r)
// Preflight requests are standalone and should stop the chain as some other
// middleware may not handle OPTIONS requests correctly. One typical example
// is authentication middleware ; OPTIONS requests won't carry authentication
// headers (see #1)
} else {
cors.logf("Handler: Actual request")
cors.handleActualRequest(w, r)
h.ServeHTTP(w, r)
}
})
}
// Martini compatible handler
func (cors *Cors) HandlerFunc(w http.ResponseWriter, r *http.Request) {
if r.Method == "OPTIONS" {
cors.logf("HandlerFunc: Preflight request")
cors.handlePreflight(w, r)
} else {
cors.logf("HandlerFunc: Actual request")
cors.handleActualRequest(w, r)
}
}
// Negroni compatible interface
func (cors *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
if r.Method == "OPTIONS" {
cors.logf("ServeHTTP: Preflight request")
cors.handlePreflight(w, r)
// Preflight requests are standalone and should stop the chain as some other
// middleware may not handle OPTIONS requests correctly. One typical example
// is authentication middleware ; OPTIONS requests won't carry authentication
// headers (see #1)
} else {
cors.logf("ServeHTTP: Actual request")
cors.handleActualRequest(w, r)
next(w, r)
}
}
// handlePreflight handles pre-flight CORS requests
func (cors *Cors) handlePreflight(w http.ResponseWriter, r *http.Request) {
options := cors.options
headers := w.Header()
origin := r.Header.Get("Origin")
if r.Method != "OPTIONS" {
cors.logf(" Preflight aborted: %s!=OPTIONS", r.Method)
return
}
if origin == "" {
cors.logf(" Preflight aborted: empty origin")
return
}
if !cors.isOriginAllowed(origin) {
cors.logf(" Preflight aborted: origin '%s' not allowed", origin)
return
}
reqMethod := r.Header.Get("Access-Control-Request-Method")
if !cors.isMethodAllowed(reqMethod) {
cors.logf(" Preflight aborted: method '%s' not allowed", reqMethod)
return
}
reqHeaders := parseHeaderList(r.Header.Get("Access-Control-Request-Headers"))
if !cors.areHeadersAllowed(reqHeaders) {
cors.logf(" Preflight aborted: headers '%v' not allowed", reqHeaders)
return
}
headers.Set("Access-Control-Allow-Origin", origin)
headers.Add("Vary", "Origin")
// Spec says: Since the list of methods can be unbounded, simply returning the method indicated
// by Access-Control-Request-Method (if supported) can be enough
headers.Set("Access-Control-Allow-Methods", strings.ToUpper(reqMethod))
if len(reqHeaders) > 0 {
// Spec says: Since the list of headers can be unbounded, simply returning supported headers
// from Access-Control-Request-Headers can be enough
headers.Set("Access-Control-Allow-Headers", strings.Join(reqHeaders, ", "))
}
if options.AllowCredentials {
headers.Set("Access-Control-Allow-Credentials", "true")
}
if options.MaxAge > 0 {
headers.Set("Access-Control-Max-Age", strconv.Itoa(options.MaxAge))
}
cors.logf(" Preflight response headers: %v", headers)
}
// handleActualRequest handles simple cross-origin requests, actual request or redirects
func (cors *Cors) handleActualRequest(w http.ResponseWriter, r *http.Request) {
options := cors.options
headers := w.Header()
origin := r.Header.Get("Origin")
if r.Method == "OPTIONS" {
cors.logf(" Actual request no headers added: method == %s", r.Method)
return
}
if origin == "" {
cors.logf(" Actual request no headers added: missing origin")
return
}
if !cors.isOriginAllowed(origin) {
cors.logf(" Actual request no headers added: origin '%s' not allowed", origin)
return
}
// Note that spec does define a way to specifically disallow a simple method like GET or
// POST. Access-Control-Allow-Methods is only used for pre-flight requests and the
// spec doesn't instruct to check the allowed methods for simple cross-origin requests.
// We think it's a nice feature to be able to have control on those methods though.
if !cors.isMethodAllowed(r.Method) {
if cors.options.Debug {
cors.logf(" Actual request no headers added: method '%s' not allowed",
r.Method)
}
return
}
headers.Set("Access-Control-Allow-Origin", origin)
headers.Add("Vary", "Origin")
if len(options.ExposedHeaders) > 0 {
headers.Set("Access-Control-Expose-Headers", strings.Join(options.ExposedHeaders, ", "))
}
if options.AllowCredentials {
headers.Set("Access-Control-Allow-Credentials", "true")
}
cors.logf(" Actual response added headers: %v", headers)
}
// convenience method. checks if debugging is turned on before printing
func (cors *Cors) logf(format string, a ...interface{}) {
if cors.options.Debug {
cors.options.log.Printf(format, a...)
}
}
// isOriginAllowed checks if a given origin is allowed to perform cross-domain requests
// on the endpoint
func (cors *Cors) isOriginAllowed(origin string) bool {
allowedOrigins := cors.options.AllowedOrigins
origin = strings.ToLower(origin)
for _, allowedOrigin := range allowedOrigins {
switch allowedOrigin {
case "*":
return true
case origin:
return true
}
}
return false
}
// isMethodAllowed checks if a given method can be used as part of a cross-domain request
// on the endpoing
func (cors *Cors) isMethodAllowed(method string) bool {
allowedMethods := cors.options.AllowedMethods
if len(allowedMethods) == 0 {
// If no method allowed, always return false, even for preflight request
return false
}
method = strings.ToUpper(method)
if method == "OPTIONS" {
// Always allow preflight requests
return true
}
for _, allowedMethod := range allowedMethods {
if allowedMethod == method {
return true
}
}
return false
}
// areHeadersAllowed checks if a given list of headers are allowed to used within
// a cross-domain request.
func (cors *Cors) areHeadersAllowed(requestedHeaders []string) bool {
if len(requestedHeaders) == 0 {
return true
}
for _, header := range requestedHeaders {
found := false
for _, allowedHeader := range cors.options.AllowedHeaders {
if allowedHeader == "*" || allowedHeader == header {
found = true
break
}
}
if !found {
return false
}
}
return true
}

View file

@ -1,27 +0,0 @@
package cors
import (
"net/http"
"strings"
)
type converter func(string) string
// convert converts a list of string using the passed converter function
func convert(s []string, c converter) []string {
out := []string{}
for _, i := range s {
out = append(out, c(i))
}
return out
}
func parseHeaderList(headerList string) (headers []string) {
for _, header := range strings.Split(headerList, ",") {
header = http.CanonicalHeaderKey(strings.TrimSpace(header))
if header != "" {
headers = append(headers, header)
}
}
return headers
}

View file

@ -1,762 +0,0 @@
// This file was generated by go generate; DO NOT EDIT
package language
// NumCompactTags is the number of common tags. The maximum tag is
// NumCompactTags-1.
const NumCompactTags = 747
var specialTags = []Tag{ // 2 elements
0: {lang: 0x61, region: 0x6d, script: 0x0, pVariant: 0x5, pExt: 0xe, str: "ca-ES-valencia"},
1: {lang: 0x9b, region: 0x132, script: 0x0, pVariant: 0x5, pExt: 0x5, str: "en-US-u-va-posix"},
} // Size: 72 bytes
var coreTags = map[uint32]uint16{
0x0: 0, // und
0x00a00000: 3, // af
0x00a000d0: 4, // af-NA
0x00a0015e: 5, // af-ZA
0x00b00000: 6, // agq
0x00b00051: 7, // agq-CM
0x00d00000: 8, // ak
0x00d0007e: 9, // ak-GH
0x01100000: 10, // am
0x0110006e: 11, // am-ET
0x01500000: 12, // ar
0x01500001: 13, // ar-001
0x01500022: 14, // ar-AE
0x01500038: 15, // ar-BH
0x01500061: 16, // ar-DJ
0x01500066: 17, // ar-DZ
0x0150006a: 18, // ar-EG
0x0150006b: 19, // ar-EH
0x0150006c: 20, // ar-ER
0x01500095: 21, // ar-IL
0x01500099: 22, // ar-IQ
0x0150009f: 23, // ar-JO
0x015000a6: 24, // ar-KM
0x015000aa: 25, // ar-KW
0x015000ae: 26, // ar-LB
0x015000b7: 27, // ar-LY
0x015000b8: 28, // ar-MA
0x015000c7: 29, // ar-MR
0x015000df: 30, // ar-OM
0x015000eb: 31, // ar-PS
0x015000f1: 32, // ar-QA
0x01500106: 33, // ar-SA
0x01500109: 34, // ar-SD
0x01500113: 35, // ar-SO
0x01500115: 36, // ar-SS
0x0150011a: 37, // ar-SY
0x0150011e: 38, // ar-TD
0x01500126: 39, // ar-TN
0x0150015b: 40, // ar-YE
0x01c00000: 41, // as
0x01c00097: 42, // as-IN
0x01d00000: 43, // asa
0x01d0012d: 44, // asa-TZ
0x01f00000: 45, // ast
0x01f0006d: 46, // ast-ES
0x02400000: 47, // az
0x0241e000: 48, // az-Cyrl
0x0241e031: 49, // az-Cyrl-AZ
0x02452000: 50, // az-Latn
0x02452031: 51, // az-Latn-AZ
0x02a00000: 52, // bas
0x02a00051: 53, // bas-CM
0x02f00000: 54, // be
0x02f00046: 55, // be-BY
0x03100000: 56, // bem
0x0310015f: 57, // bem-ZM
0x03300000: 58, // bez
0x0330012d: 59, // bez-TZ
0x03800000: 60, // bg
0x03800037: 61, // bg-BG
0x03c00000: 62, // bh
0x04900000: 63, // bm
0x049000c1: 64, // bm-ML
0x04b00000: 65, // bn
0x04b00034: 66, // bn-BD
0x04b00097: 67, // bn-IN
0x04c00000: 68, // bo
0x04c00052: 69, // bo-CN
0x04c00097: 70, // bo-IN
0x05000000: 71, // br
0x05000076: 72, // br-FR
0x05300000: 73, // brx
0x05300097: 74, // brx-IN
0x05400000: 75, // bs
0x0541e000: 76, // bs-Cyrl
0x0541e032: 77, // bs-Cyrl-BA
0x05452000: 78, // bs-Latn
0x05452032: 79, // bs-Latn-BA
0x06100000: 80, // ca
0x06100021: 81, // ca-AD
0x0610006d: 82, // ca-ES
0x06100076: 83, // ca-FR
0x0610009c: 84, // ca-IT
0x06400000: 85, // ce
0x06400104: 86, // ce-RU
0x06600000: 87, // cgg
0x0660012f: 88, // cgg-UG
0x06c00000: 89, // chr
0x06c00132: 90, // chr-US
0x06f00000: 91, // ckb
0x06f00099: 92, // ckb-IQ
0x06f0009a: 93, // ckb-IR
0x07900000: 94, // cs
0x0790005d: 95, // cs-CZ
0x07d00000: 96, // cu
0x07d00104: 97, // cu-RU
0x07f00000: 98, // cy
0x07f00079: 99, // cy-GB
0x08000000: 100, // da
0x08000062: 101, // da-DK
0x08000080: 102, // da-GL
0x08300000: 103, // dav
0x083000a2: 104, // dav-KE
0x08500000: 105, // de
0x0850002d: 106, // de-AT
0x08500035: 107, // de-BE
0x0850004d: 108, // de-CH
0x0850005f: 109, // de-DE
0x085000b0: 110, // de-LI
0x085000b5: 111, // de-LU
0x08800000: 112, // dje
0x088000d2: 113, // dje-NE
0x08b00000: 114, // dsb
0x08b0005f: 115, // dsb-DE
0x08f00000: 116, // dua
0x08f00051: 117, // dua-CM
0x09000000: 118, // dv
0x09100000: 119, // dyo
0x09100112: 120, // dyo-SN
0x09300000: 121, // dz
0x09300042: 122, // dz-BT
0x09400000: 123, // ebu
0x094000a2: 124, // ebu-KE
0x09500000: 125, // ee
0x0950007e: 126, // ee-GH
0x09500120: 127, // ee-TG
0x09a00000: 128, // el
0x09a0005c: 129, // el-CY
0x09a00085: 130, // el-GR
0x09b00000: 131, // en
0x09b00001: 132, // en-001
0x09b0001a: 133, // en-150
0x09b00024: 134, // en-AG
0x09b00025: 135, // en-AI
0x09b0002c: 136, // en-AS
0x09b0002d: 137, // en-AT
0x09b0002e: 138, // en-AU
0x09b00033: 139, // en-BB
0x09b00035: 140, // en-BE
0x09b00039: 141, // en-BI
0x09b0003c: 142, // en-BM
0x09b00041: 143, // en-BS
0x09b00045: 144, // en-BW
0x09b00047: 145, // en-BZ
0x09b00048: 146, // en-CA
0x09b00049: 147, // en-CC
0x09b0004d: 148, // en-CH
0x09b0004f: 149, // en-CK
0x09b00051: 150, // en-CM
0x09b0005b: 151, // en-CX
0x09b0005c: 152, // en-CY
0x09b0005f: 153, // en-DE
0x09b00060: 154, // en-DG
0x09b00062: 155, // en-DK
0x09b00063: 156, // en-DM
0x09b0006c: 157, // en-ER
0x09b00070: 158, // en-FI
0x09b00071: 159, // en-FJ
0x09b00072: 160, // en-FK
0x09b00073: 161, // en-FM
0x09b00079: 162, // en-GB
0x09b0007a: 163, // en-GD
0x09b0007d: 164, // en-GG
0x09b0007e: 165, // en-GH
0x09b0007f: 166, // en-GI
0x09b00081: 167, // en-GM
0x09b00088: 168, // en-GU
0x09b0008a: 169, // en-GY
0x09b0008b: 170, // en-HK
0x09b00094: 171, // en-IE
0x09b00095: 172, // en-IL
0x09b00096: 173, // en-IM
0x09b00097: 174, // en-IN
0x09b00098: 175, // en-IO
0x09b0009d: 176, // en-JE
0x09b0009e: 177, // en-JM
0x09b000a2: 178, // en-KE
0x09b000a5: 179, // en-KI
0x09b000a7: 180, // en-KN
0x09b000ab: 181, // en-KY
0x09b000af: 182, // en-LC
0x09b000b2: 183, // en-LR
0x09b000b3: 184, // en-LS
0x09b000bd: 185, // en-MG
0x09b000be: 186, // en-MH
0x09b000c4: 187, // en-MO
0x09b000c5: 188, // en-MP
0x09b000c8: 189, // en-MS
0x09b000c9: 190, // en-MT
0x09b000ca: 191, // en-MU
0x09b000cc: 192, // en-MW
0x09b000ce: 193, // en-MY
0x09b000d0: 194, // en-NA
0x09b000d3: 195, // en-NF
0x09b000d4: 196, // en-NG
0x09b000d7: 197, // en-NL
0x09b000db: 198, // en-NR
0x09b000dd: 199, // en-NU
0x09b000de: 200, // en-NZ
0x09b000e4: 201, // en-PG
0x09b000e5: 202, // en-PH
0x09b000e6: 203, // en-PK
0x09b000e9: 204, // en-PN
0x09b000ea: 205, // en-PR
0x09b000ee: 206, // en-PW
0x09b00105: 207, // en-RW
0x09b00107: 208, // en-SB
0x09b00108: 209, // en-SC
0x09b00109: 210, // en-SD
0x09b0010a: 211, // en-SE
0x09b0010b: 212, // en-SG
0x09b0010c: 213, // en-SH
0x09b0010d: 214, // en-SI
0x09b00110: 215, // en-SL
0x09b00115: 216, // en-SS
0x09b00119: 217, // en-SX
0x09b0011b: 218, // en-SZ
0x09b0011d: 219, // en-TC
0x09b00123: 220, // en-TK
0x09b00127: 221, // en-TO
0x09b0012a: 222, // en-TT
0x09b0012b: 223, // en-TV
0x09b0012d: 224, // en-TZ
0x09b0012f: 225, // en-UG
0x09b00131: 226, // en-UM
0x09b00132: 227, // en-US
0x09b00136: 228, // en-VC
0x09b00139: 229, // en-VG
0x09b0013a: 230, // en-VI
0x09b0013c: 231, // en-VU
0x09b0013f: 232, // en-WS
0x09b0015e: 233, // en-ZA
0x09b0015f: 234, // en-ZM
0x09b00161: 235, // en-ZW
0x09c00000: 236, // eo
0x09c00001: 237, // eo-001
0x09d00000: 238, // es
0x09d0001e: 239, // es-419
0x09d0002b: 240, // es-AR
0x09d0003e: 241, // es-BO
0x09d00040: 242, // es-BR
0x09d00050: 243, // es-CL
0x09d00053: 244, // es-CO
0x09d00055: 245, // es-CR
0x09d00058: 246, // es-CU
0x09d00064: 247, // es-DO
0x09d00067: 248, // es-EA
0x09d00068: 249, // es-EC
0x09d0006d: 250, // es-ES
0x09d00084: 251, // es-GQ
0x09d00087: 252, // es-GT
0x09d0008d: 253, // es-HN
0x09d00092: 254, // es-IC
0x09d000cd: 255, // es-MX
0x09d000d6: 256, // es-NI
0x09d000e0: 257, // es-PA
0x09d000e2: 258, // es-PE
0x09d000e5: 259, // es-PH
0x09d000ea: 260, // es-PR
0x09d000ef: 261, // es-PY
0x09d00118: 262, // es-SV
0x09d00132: 263, // es-US
0x09d00133: 264, // es-UY
0x09d00138: 265, // es-VE
0x09f00000: 266, // et
0x09f00069: 267, // et-EE
0x0a100000: 268, // eu
0x0a10006d: 269, // eu-ES
0x0a200000: 270, // ewo
0x0a200051: 271, // ewo-CM
0x0a400000: 272, // fa
0x0a400023: 273, // fa-AF
0x0a40009a: 274, // fa-IR
0x0a600000: 275, // ff
0x0a600051: 276, // ff-CM
0x0a600082: 277, // ff-GN
0x0a6000c7: 278, // ff-MR
0x0a600112: 279, // ff-SN
0x0a800000: 280, // fi
0x0a800070: 281, // fi-FI
0x0aa00000: 282, // fil
0x0aa000e5: 283, // fil-PH
0x0ad00000: 284, // fo
0x0ad00062: 285, // fo-DK
0x0ad00074: 286, // fo-FO
0x0af00000: 287, // fr
0x0af00035: 288, // fr-BE
0x0af00036: 289, // fr-BF
0x0af00039: 290, // fr-BI
0x0af0003a: 291, // fr-BJ
0x0af0003b: 292, // fr-BL
0x0af00048: 293, // fr-CA
0x0af0004a: 294, // fr-CD
0x0af0004b: 295, // fr-CF
0x0af0004c: 296, // fr-CG
0x0af0004d: 297, // fr-CH
0x0af0004e: 298, // fr-CI
0x0af00051: 299, // fr-CM
0x0af00061: 300, // fr-DJ
0x0af00066: 301, // fr-DZ
0x0af00076: 302, // fr-FR
0x0af00078: 303, // fr-GA
0x0af0007c: 304, // fr-GF
0x0af00082: 305, // fr-GN
0x0af00083: 306, // fr-GP
0x0af00084: 307, // fr-GQ
0x0af0008f: 308, // fr-HT
0x0af000a6: 309, // fr-KM
0x0af000b5: 310, // fr-LU
0x0af000b8: 311, // fr-MA
0x0af000b9: 312, // fr-MC
0x0af000bc: 313, // fr-MF
0x0af000bd: 314, // fr-MG
0x0af000c1: 315, // fr-ML
0x0af000c6: 316, // fr-MQ
0x0af000c7: 317, // fr-MR
0x0af000ca: 318, // fr-MU
0x0af000d1: 319, // fr-NC
0x0af000d2: 320, // fr-NE
0x0af000e3: 321, // fr-PF
0x0af000e8: 322, // fr-PM
0x0af00100: 323, // fr-RE
0x0af00105: 324, // fr-RW
0x0af00108: 325, // fr-SC
0x0af00112: 326, // fr-SN
0x0af0011a: 327, // fr-SY
0x0af0011e: 328, // fr-TD
0x0af00120: 329, // fr-TG
0x0af00126: 330, // fr-TN
0x0af0013c: 331, // fr-VU
0x0af0013d: 332, // fr-WF
0x0af0015c: 333, // fr-YT
0x0b600000: 334, // fur
0x0b60009c: 335, // fur-IT
0x0b900000: 336, // fy
0x0b9000d7: 337, // fy-NL
0x0ba00000: 338, // ga
0x0ba00094: 339, // ga-IE
0x0c200000: 340, // gd
0x0c200079: 341, // gd-GB
0x0c800000: 342, // gl
0x0c80006d: 343, // gl-ES
0x0d200000: 344, // gsw
0x0d20004d: 345, // gsw-CH
0x0d200076: 346, // gsw-FR
0x0d2000b0: 347, // gsw-LI
0x0d300000: 348, // gu
0x0d300097: 349, // gu-IN
0x0d700000: 350, // guw
0x0d800000: 351, // guz
0x0d8000a2: 352, // guz-KE
0x0d900000: 353, // gv
0x0d900096: 354, // gv-IM
0x0dc00000: 355, // ha
0x0dc0007e: 356, // ha-GH
0x0dc000d2: 357, // ha-NE
0x0dc000d4: 358, // ha-NG
0x0de00000: 359, // haw
0x0de00132: 360, // haw-US
0x0e000000: 361, // he
0x0e000095: 362, // he-IL
0x0e100000: 363, // hi
0x0e100097: 364, // hi-IN
0x0ee00000: 365, // hr
0x0ee00032: 366, // hr-BA
0x0ee0008e: 367, // hr-HR
0x0ef00000: 368, // hsb
0x0ef0005f: 369, // hsb-DE
0x0f200000: 370, // hu
0x0f200090: 371, // hu-HU
0x0f300000: 372, // hy
0x0f300027: 373, // hy-AM
0x0f800000: 374, // id
0x0f800093: 375, // id-ID
0x0fa00000: 376, // ig
0x0fa000d4: 377, // ig-NG
0x0fb00000: 378, // ii
0x0fb00052: 379, // ii-CN
0x10200000: 380, // is
0x1020009b: 381, // is-IS
0x10300000: 382, // it
0x1030004d: 383, // it-CH
0x1030009c: 384, // it-IT
0x10300111: 385, // it-SM
0x10400000: 386, // iu
0x10700000: 387, // ja
0x107000a0: 388, // ja-JP
0x10900000: 389, // jbo
0x10a00000: 390, // jgo
0x10a00051: 391, // jgo-CM
0x10c00000: 392, // jmc
0x10c0012d: 393, // jmc-TZ
0x10f00000: 394, // jv
0x11100000: 395, // ka
0x1110007b: 396, // ka-GE
0x11300000: 397, // kab
0x11300066: 398, // kab-DZ
0x11500000: 399, // kaj
0x11600000: 400, // kam
0x116000a2: 401, // kam-KE
0x11900000: 402, // kcg
0x11b00000: 403, // kde
0x11b0012d: 404, // kde-TZ
0x11d00000: 405, // kea
0x11d00059: 406, // kea-CV
0x12800000: 407, // khq
0x128000c1: 408, // khq-ML
0x12b00000: 409, // ki
0x12b000a2: 410, // ki-KE
0x12f00000: 411, // kk
0x12f000ac: 412, // kk-KZ
0x13000000: 413, // kkj
0x13000051: 414, // kkj-CM
0x13100000: 415, // kl
0x13100080: 416, // kl-GL
0x13200000: 417, // kln
0x132000a2: 418, // kln-KE
0x13300000: 419, // km
0x133000a4: 420, // km-KH
0x13500000: 421, // kn
0x13500097: 422, // kn-IN
0x13600000: 423, // ko
0x136000a8: 424, // ko-KP
0x136000a9: 425, // ko-KR
0x13800000: 426, // kok
0x13800097: 427, // kok-IN
0x14100000: 428, // ks
0x14100097: 429, // ks-IN
0x14200000: 430, // ksb
0x1420012d: 431, // ksb-TZ
0x14300000: 432, // ksf
0x14300051: 433, // ksf-CM
0x14400000: 434, // ksh
0x1440005f: 435, // ksh-DE
0x14500000: 436, // ku
0x14a00000: 437, // kw
0x14a00079: 438, // kw-GB
0x14d00000: 439, // ky
0x14d000a3: 440, // ky-KG
0x15100000: 441, // lag
0x1510012d: 442, // lag-TZ
0x15400000: 443, // lb
0x154000b5: 444, // lb-LU
0x15a00000: 445, // lg
0x15a0012f: 446, // lg-UG
0x16100000: 447, // lkt
0x16100132: 448, // lkt-US
0x16400000: 449, // ln
0x16400029: 450, // ln-AO
0x1640004a: 451, // ln-CD
0x1640004b: 452, // ln-CF
0x1640004c: 453, // ln-CG
0x16500000: 454, // lo
0x165000ad: 455, // lo-LA
0x16800000: 456, // lrc
0x16800099: 457, // lrc-IQ
0x1680009a: 458, // lrc-IR
0x16900000: 459, // lt
0x169000b4: 460, // lt-LT
0x16b00000: 461, // lu
0x16b0004a: 462, // lu-CD
0x16d00000: 463, // luo
0x16d000a2: 464, // luo-KE
0x16e00000: 465, // luy
0x16e000a2: 466, // luy-KE
0x17000000: 467, // lv
0x170000b6: 468, // lv-LV
0x17a00000: 469, // mas
0x17a000a2: 470, // mas-KE
0x17a0012d: 471, // mas-TZ
0x18000000: 472, // mer
0x180000a2: 473, // mer-KE
0x18200000: 474, // mfe
0x182000ca: 475, // mfe-MU
0x18300000: 476, // mg
0x183000bd: 477, // mg-MG
0x18400000: 478, // mgh
0x184000cf: 479, // mgh-MZ
0x18500000: 480, // mgo
0x18500051: 481, // mgo-CM
0x18c00000: 482, // mk
0x18c000c0: 483, // mk-MK
0x18d00000: 484, // ml
0x18d00097: 485, // ml-IN
0x18f00000: 486, // mn
0x18f000c3: 487, // mn-MN
0x19600000: 488, // mr
0x19600097: 489, // mr-IN
0x19a00000: 490, // ms
0x19a0003d: 491, // ms-BN
0x19a000ce: 492, // ms-MY
0x19a0010b: 493, // ms-SG
0x19b00000: 494, // mt
0x19b000c9: 495, // mt-MT
0x19d00000: 496, // mua
0x19d00051: 497, // mua-CM
0x1a500000: 498, // my
0x1a5000c2: 499, // my-MM
0x1a900000: 500, // mzn
0x1a90009a: 501, // mzn-IR
0x1ab00000: 502, // nah
0x1ae00000: 503, // naq
0x1ae000d0: 504, // naq-NA
0x1af00000: 505, // nb
0x1af000d8: 506, // nb-NO
0x1af0010e: 507, // nb-SJ
0x1b100000: 508, // nd
0x1b100161: 509, // nd-ZW
0x1b400000: 510, // ne
0x1b400097: 511, // ne-IN
0x1b4000d9: 512, // ne-NP
0x1bd00000: 513, // nl
0x1bd0002f: 514, // nl-AW
0x1bd00035: 515, // nl-BE
0x1bd0003f: 516, // nl-BQ
0x1bd0005a: 517, // nl-CW
0x1bd000d7: 518, // nl-NL
0x1bd00114: 519, // nl-SR
0x1bd00119: 520, // nl-SX
0x1be00000: 521, // nmg
0x1be00051: 522, // nmg-CM
0x1bf00000: 523, // nn
0x1bf000d8: 524, // nn-NO
0x1c000000: 525, // nnh
0x1c000051: 526, // nnh-CM
0x1c100000: 527, // no
0x1c500000: 528, // nqo
0x1c600000: 529, // nr
0x1c800000: 530, // nso
0x1c900000: 531, // nus
0x1c900115: 532, // nus-SS
0x1cc00000: 533, // ny
0x1ce00000: 534, // nyn
0x1ce0012f: 535, // nyn-UG
0x1d200000: 536, // om
0x1d20006e: 537, // om-ET
0x1d2000a2: 538, // om-KE
0x1d300000: 539, // or
0x1d300097: 540, // or-IN
0x1d400000: 541, // os
0x1d40007b: 542, // os-GE
0x1d400104: 543, // os-RU
0x1d700000: 544, // pa
0x1d705000: 545, // pa-Arab
0x1d7050e6: 546, // pa-Arab-PK
0x1d72f000: 547, // pa-Guru
0x1d72f097: 548, // pa-Guru-IN
0x1db00000: 549, // pap
0x1e700000: 550, // pl
0x1e7000e7: 551, // pl-PL
0x1ed00000: 552, // prg
0x1ed00001: 553, // prg-001
0x1ee00000: 554, // ps
0x1ee00023: 555, // ps-AF
0x1ef00000: 556, // pt
0x1ef00029: 557, // pt-AO
0x1ef00040: 558, // pt-BR
0x1ef0004d: 559, // pt-CH
0x1ef00059: 560, // pt-CV
0x1ef00084: 561, // pt-GQ
0x1ef00089: 562, // pt-GW
0x1ef000b5: 563, // pt-LU
0x1ef000c4: 564, // pt-MO
0x1ef000cf: 565, // pt-MZ
0x1ef000ec: 566, // pt-PT
0x1ef00116: 567, // pt-ST
0x1ef00124: 568, // pt-TL
0x1f100000: 569, // qu
0x1f10003e: 570, // qu-BO
0x1f100068: 571, // qu-EC
0x1f1000e2: 572, // qu-PE
0x1fc00000: 573, // rm
0x1fc0004d: 574, // rm-CH
0x20100000: 575, // rn
0x20100039: 576, // rn-BI
0x20300000: 577, // ro
0x203000ba: 578, // ro-MD
0x20300102: 579, // ro-RO
0x20500000: 580, // rof
0x2050012d: 581, // rof-TZ
0x20700000: 582, // ru
0x20700046: 583, // ru-BY
0x207000a3: 584, // ru-KG
0x207000ac: 585, // ru-KZ
0x207000ba: 586, // ru-MD
0x20700104: 587, // ru-RU
0x2070012e: 588, // ru-UA
0x20a00000: 589, // rw
0x20a00105: 590, // rw-RW
0x20b00000: 591, // rwk
0x20b0012d: 592, // rwk-TZ
0x20f00000: 593, // sah
0x20f00104: 594, // sah-RU
0x21000000: 595, // saq
0x210000a2: 596, // saq-KE
0x21400000: 597, // sbp
0x2140012d: 598, // sbp-TZ
0x21c00000: 599, // sdh
0x21d00000: 600, // se
0x21d00070: 601, // se-FI
0x21d000d8: 602, // se-NO
0x21d0010a: 603, // se-SE
0x21f00000: 604, // seh
0x21f000cf: 605, // seh-MZ
0x22100000: 606, // ses
0x221000c1: 607, // ses-ML
0x22200000: 608, // sg
0x2220004b: 609, // sg-CF
0x22600000: 610, // shi
0x22652000: 611, // shi-Latn
0x226520b8: 612, // shi-Latn-MA
0x226d2000: 613, // shi-Tfng
0x226d20b8: 614, // shi-Tfng-MA
0x22800000: 615, // si
0x228000b1: 616, // si-LK
0x22a00000: 617, // sk
0x22a0010f: 618, // sk-SK
0x22c00000: 619, // sl
0x22c0010d: 620, // sl-SI
0x23000000: 621, // sma
0x23100000: 622, // smi
0x23200000: 623, // smj
0x23300000: 624, // smn
0x23300070: 625, // smn-FI
0x23500000: 626, // sms
0x23600000: 627, // sn
0x23600161: 628, // sn-ZW
0x23800000: 629, // so
0x23800061: 630, // so-DJ
0x2380006e: 631, // so-ET
0x238000a2: 632, // so-KE
0x23800113: 633, // so-SO
0x23a00000: 634, // sq
0x23a00026: 635, // sq-AL
0x23a000c0: 636, // sq-MK
0x23a0014a: 637, // sq-XK
0x23b00000: 638, // sr
0x23b1e000: 639, // sr-Cyrl
0x23b1e032: 640, // sr-Cyrl-BA
0x23b1e0bb: 641, // sr-Cyrl-ME
0x23b1e103: 642, // sr-Cyrl-RS
0x23b1e14a: 643, // sr-Cyrl-XK
0x23b52000: 644, // sr-Latn
0x23b52032: 645, // sr-Latn-BA
0x23b520bb: 646, // sr-Latn-ME
0x23b52103: 647, // sr-Latn-RS
0x23b5214a: 648, // sr-Latn-XK
0x24000000: 649, // ss
0x24100000: 650, // ssy
0x24200000: 651, // st
0x24700000: 652, // sv
0x24700030: 653, // sv-AX
0x24700070: 654, // sv-FI
0x2470010a: 655, // sv-SE
0x24800000: 656, // sw
0x2480004a: 657, // sw-CD
0x248000a2: 658, // sw-KE
0x2480012d: 659, // sw-TZ
0x2480012f: 660, // sw-UG
0x24f00000: 661, // syr
0x25100000: 662, // ta
0x25100097: 663, // ta-IN
0x251000b1: 664, // ta-LK
0x251000ce: 665, // ta-MY
0x2510010b: 666, // ta-SG
0x25800000: 667, // te
0x25800097: 668, // te-IN
0x25a00000: 669, // teo
0x25a000a2: 670, // teo-KE
0x25a0012f: 671, // teo-UG
0x25d00000: 672, // th
0x25d00121: 673, // th-TH
0x26100000: 674, // ti
0x2610006c: 675, // ti-ER
0x2610006e: 676, // ti-ET
0x26200000: 677, // tig
0x26400000: 678, // tk
0x26400125: 679, // tk-TM
0x26b00000: 680, // tn
0x26c00000: 681, // to
0x26c00127: 682, // to-TO
0x26f00000: 683, // tr
0x26f0005c: 684, // tr-CY
0x26f00129: 685, // tr-TR
0x27200000: 686, // ts
0x27e00000: 687, // twq
0x27e000d2: 688, // twq-NE
0x28200000: 689, // tzm
0x282000b8: 690, // tzm-MA
0x28400000: 691, // ug
0x28400052: 692, // ug-CN
0x28600000: 693, // uk
0x2860012e: 694, // uk-UA
0x28c00000: 695, // ur
0x28c00097: 696, // ur-IN
0x28c000e6: 697, // ur-PK
0x28d00000: 698, // uz
0x28d05000: 699, // uz-Arab
0x28d05023: 700, // uz-Arab-AF
0x28d1e000: 701, // uz-Cyrl
0x28d1e134: 702, // uz-Cyrl-UZ
0x28d52000: 703, // uz-Latn
0x28d52134: 704, // uz-Latn-UZ
0x28e00000: 705, // vai
0x28e52000: 706, // vai-Latn
0x28e520b2: 707, // vai-Latn-LR
0x28ed9000: 708, // vai-Vaii
0x28ed90b2: 709, // vai-Vaii-LR
0x28f00000: 710, // ve
0x29200000: 711, // vi
0x2920013b: 712, // vi-VN
0x29700000: 713, // vo
0x29700001: 714, // vo-001
0x29a00000: 715, // vun
0x29a0012d: 716, // vun-TZ
0x29b00000: 717, // wa
0x29c00000: 718, // wae
0x29c0004d: 719, // wae-CH
0x2a400000: 720, // wo
0x2a900000: 721, // xh
0x2b100000: 722, // xog
0x2b10012f: 723, // xog-UG
0x2b700000: 724, // yav
0x2b700051: 725, // yav-CM
0x2b900000: 726, // yi
0x2b900001: 727, // yi-001
0x2ba00000: 728, // yo
0x2ba0003a: 729, // yo-BJ
0x2ba000d4: 730, // yo-NG
0x2bd00000: 731, // yue
0x2bd0008b: 732, // yue-HK
0x2c300000: 733, // zgh
0x2c3000b8: 734, // zgh-MA
0x2c400000: 735, // zh
0x2c434000: 736, // zh-Hans
0x2c434052: 737, // zh-Hans-CN
0x2c43408b: 738, // zh-Hans-HK
0x2c4340c4: 739, // zh-Hans-MO
0x2c43410b: 740, // zh-Hans-SG
0x2c435000: 741, // zh-Hant
0x2c43508b: 742, // zh-Hant-HK
0x2c4350c4: 743, // zh-Hant-MO
0x2c43512c: 744, // zh-Hant-TW
0x2c600000: 745, // zu
0x2c60015e: 746, // zu-ZA
}
// Total table size 4550 bytes (4KiB); checksum: B6D49547

File diff suppressed because it is too large Load diff

View file

@ -1,23 +0,0 @@
language: go
sudo: false
go:
- 1.1.2
- 1.2.2
- 1.3.3
- 1.4
- 1.5.4
- 1.6.2
- tip
matrix:
allow_failures:
- go: tip
before_script:
- go get github.com/meatballhat/gfmxr/...
script:
- go vet ./...
- go test -v ./...
- gfmxr -c $(grep -c 'package main' README.md) -s README.md

View file

@ -1,21 +0,0 @@
Copyright (C) 2013 Jeremy Saenz
All Rights Reserved.
MIT LICENSE
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,579 +0,0 @@
[![Coverage](http://gocover.io/_badge/github.com/codegangsta/cli?0)](http://gocover.io/github.com/codegangsta/cli)
[![Build Status](https://travis-ci.org/codegangsta/cli.svg?branch=master)](https://travis-ci.org/codegangsta/cli)
[![GoDoc](https://godoc.org/github.com/codegangsta/cli?status.svg)](https://godoc.org/github.com/codegangsta/cli)
[![codebeat](https://codebeat.co/badges/0a8f30aa-f975-404b-b878-5fab3ae1cc5f)](https://codebeat.co/projects/github-com-codegangsta-cli)
[![Go Report Card](https://goreportcard.com/badge/codegangsta/cli)](https://goreportcard.com/report/codegangsta/cli)
# cli
cli is a simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.
## Overview
Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app.
**This is where cli comes into play.** cli makes command line programming fun, organized, and expressive!
## Installation
Make sure you have a working Go environment (go 1.1+ is *required*). [See the install instructions](http://golang.org/doc/install.html).
To install cli, simply run:
```
$ go get github.com/codegangsta/cli
```
Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands can be easily used:
```
export PATH=$PATH:$GOPATH/bin
```
## Getting Started
One of the philosophies behind cli is that an API should be playful and full of discovery. So a cli app can be as little as one line of code in `main()`.
``` go
package main
import (
"os"
"github.com/codegangsta/cli"
)
func main() {
cli.NewApp().Run(os.Args)
}
```
This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation:
<!-- {
"output": "boom! I say!"
} -->
``` go
package main
import (
"fmt"
"os"
"github.com/codegangsta/cli"
)
func main() {
app := cli.NewApp()
app.Name = "boom"
app.Usage = "make an explosive entrance"
app.Action = func(c *cli.Context) error {
fmt.Println("boom! I say!")
return nil
}
app.Run(os.Args)
}
```
Running this already gives you a ton of functionality, plus support for things like subcommands and flags, which are covered below.
## Example
Being a programmer can be a lonely job. Thankfully by the power of automation that is not the case! Let's create a greeter app to fend off our demons of loneliness!
Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it:
<!-- {
"output": "Hello friend!"
} -->
``` go
package main
import (
"fmt"
"os"
"github.com/codegangsta/cli"
)
func main() {
app := cli.NewApp()
app.Name = "greet"
app.Usage = "fight the loneliness!"
app.Action = func(c *cli.Context) error {
fmt.Println("Hello friend!")
return nil
}
app.Run(os.Args)
}
```
Install our command to the `$GOPATH/bin` directory:
```
$ go install
```
Finally run our new command:
```
$ greet
Hello friend!
```
cli also generates neat help text:
```
$ greet help
NAME:
greet - fight the loneliness!
USAGE:
greet [global options] command [command options] [arguments...]
VERSION:
0.0.0
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS
--version Shows version information
```
### Arguments
You can lookup arguments by calling the `Args` function on `cli.Context`.
``` go
...
app.Action = func(c *cli.Context) error {
fmt.Println("Hello", c.Args()[0])
return nil
}
...
```
### Flags
Setting and querying flags is simple.
``` go
...
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "lang",
Value: "english",
Usage: "language for the greeting",
},
}
app.Action = func(c *cli.Context) error {
name := "someone"
if c.NArg() > 0 {
name = c.Args()[0]
}
if c.String("lang") == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
}
...
```
You can also set a destination variable for a flag, to which the content will be scanned.
``` go
...
var language string
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "lang",
Value: "english",
Usage: "language for the greeting",
Destination: &language,
},
}
app.Action = func(c *cli.Context) error {
name := "someone"
if c.NArg() > 0 {
name = c.Args()[0]
}
if language == "spanish" {
fmt.Println("Hola", name)
} else {
fmt.Println("Hello", name)
}
return nil
}
...
```
See full list of flags at http://godoc.org/github.com/codegangsta/cli
#### Placeholder Values
Sometimes it's useful to specify a flag's value within the usage string itself. Such placeholders are
indicated with back quotes.
For example this:
```go
cli.StringFlag{
Name: "config, c",
Usage: "Load configuration from `FILE`",
}
```
Will result in help output like:
```
--config FILE, -c FILE Load configuration from FILE
```
Note that only the first placeholder is used. Subsequent back-quoted words will be left as-is.
#### Alternate Names
You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g.
``` go
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "lang, l",
Value: "english",
Usage: "language for the greeting",
},
}
```
That flag can then be set with `--lang spanish` or `-l spanish`. Note that giving two different forms of the same flag in the same command invocation is an error.
#### Values from the Environment
You can also have the default value set from the environment via `EnvVar`. e.g.
``` go
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "lang, l",
Value: "english",
Usage: "language for the greeting",
EnvVar: "APP_LANG",
},
}
```
The `EnvVar` may also be given as a comma-delimited "cascade", where the first environment variable that resolves is used as the default.
``` go
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "lang, l",
Value: "english",
Usage: "language for the greeting",
EnvVar: "LEGACY_COMPAT_LANG,APP_LANG,LANG",
},
}
```
#### Values from alternate input sources (YAML and others)
There is a separate package altsrc that adds support for getting flag values from other input sources like YAML.
In order to get values for a flag from an alternate input source the following code would be added to wrap an existing cli.Flag like below:
``` go
altsrc.NewIntFlag(cli.IntFlag{Name: "test"})
```
Initialization must also occur for these flags. Below is an example initializing getting data from a yaml file below.
``` go
command.Before = altsrc.InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
```
The code above will use the "load" string as a flag name to get the file name of a yaml file from the cli.Context.
It will then use that file name to initialize the yaml input source for any flags that are defined on that command.
As a note the "load" flag used would also have to be defined on the command flags in order for this code snipped to work.
Currently only YAML files are supported but developers can add support for other input sources by implementing the
altsrc.InputSourceContext for their given sources.
Here is a more complete sample of a command using YAML support:
``` go
command := &cli.Command{
Name: "test-cmd",
Aliases: []string{"tc"},
Usage: "this is for testing",
Description: "testing",
Action: func(c *cli.Context) error {
// Action to run
return nil
},
Flags: []cli.Flag{
NewIntFlag(cli.IntFlag{Name: "test"}),
cli.StringFlag{Name: "load"}},
}
command.Before = InitInputSourceWithContext(command.Flags, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
```
### Subcommands
Subcommands can be defined for a more git-like command line app.
```go
...
app.Commands = []cli.Command{
{
Name: "add",
Aliases: []string{"a"},
Usage: "add a task to the list",
Action: func(c *cli.Context) error {
fmt.Println("added task: ", c.Args().First())
return nil
},
},
{
Name: "complete",
Aliases: []string{"c"},
Usage: "complete a task on the list",
Action: func(c *cli.Context) error {
fmt.Println("completed task: ", c.Args().First())
return nil
},
},
{
Name: "template",
Aliases: []string{"r"},
Usage: "options for task templates",
Subcommands: []cli.Command{
{
Name: "add",
Usage: "add a new template",
Action: func(c *cli.Context) error {
fmt.Println("new task template: ", c.Args().First())
return nil
},
},
{
Name: "remove",
Usage: "remove an existing template",
Action: func(c *cli.Context) error {
fmt.Println("removed task template: ", c.Args().First())
return nil
},
},
},
},
}
...
```
### Subcommands categories
For additional organization in apps that have many subcommands, you can
associate a category for each command to group them together in the help
output.
E.g.
```go
...
app.Commands = []cli.Command{
{
Name: "noop",
},
{
Name: "add",
Category: "template",
},
{
Name: "remove",
Category: "template",
},
}
...
```
Will include:
```
...
COMMANDS:
noop
Template actions:
add
remove
...
```
### Exit code
Calling `App.Run` will not automatically call `os.Exit`, which means that by
default the exit code will "fall through" to being `0`. An explicit exit code
may be set by returning a non-nil error that fulfills `cli.ExitCoder`, *or* a
`cli.MultiError` that includes an error that fulfills `cli.ExitCoder`, e.g.:
``` go
package main
import (
"os"
"github.com/codegangsta/cli"
)
func main() {
app := cli.NewApp()
app.Flags = []cli.Flag{
cli.BoolTFlag{
Name: "ginger-crouton",
Usage: "is it in the soup?",
},
}
app.Action = func(ctx *cli.Context) error {
if !ctx.Bool("ginger-crouton") {
return cli.NewExitError("it is not in the soup", 86)
}
return nil
}
app.Run(os.Args)
}
```
### Bash Completion
You can enable completion commands by setting the `EnableBashCompletion`
flag on the `App` object. By default, this setting will only auto-complete to
show an app's subcommands, but you can write your own completion methods for
the App or its subcommands.
```go
...
var tasks = []string{"cook", "clean", "laundry", "eat", "sleep", "code"}
app := cli.NewApp()
app.EnableBashCompletion = true
app.Commands = []cli.Command{
{
Name: "complete",
Aliases: []string{"c"},
Usage: "complete a task on the list",
Action: func(c *cli.Context) error {
fmt.Println("completed task: ", c.Args().First())
return nil
},
BashComplete: func(c *cli.Context) {
// This will complete if no args are passed
if c.NArg() > 0 {
return
}
for _, t := range tasks {
fmt.Println(t)
}
},
}
}
...
```
#### To Enable
Source the `autocomplete/bash_autocomplete` file in your `.bashrc` file while
setting the `PROG` variable to the name of your program:
`PROG=myprogram source /.../cli/autocomplete/bash_autocomplete`
#### To Distribute
Copy `autocomplete/bash_autocomplete` into `/etc/bash_completion.d/` and rename
it to the name of the program you wish to add autocomplete support for (or
automatically install it there if you are distributing a package). Don't forget
to source the file to make it active in the current shell.
```
sudo cp src/bash_autocomplete /etc/bash_completion.d/<myprogram>
source /etc/bash_completion.d/<myprogram>
```
Alternatively, you can just document that users should source the generic
`autocomplete/bash_autocomplete` in their bash configuration with `$PROG` set
to the name of their program (as above).
### Generated Help Text Customization
All of the help text generation may be customized, and at multiple levels. The
templates are exposed as variables `AppHelpTemplate`, `CommandHelpTemplate`, and
`SubcommandHelpTemplate` which may be reassigned or augmented, and full override
is possible by assigning a compatible func to the `cli.HelpPrinter` variable,
e.g.:
<!-- {
"output": "Ha HA. I pwnd the help!!1"
} -->
``` go
package main
import (
"fmt"
"io"
"os"
"github.com/codegangsta/cli"
)
func main() {
// EXAMPLE: Append to an existing template
cli.AppHelpTemplate = fmt.Sprintf(`%s
WEBSITE: http://awesometown.example.com
SUPPORT: support@awesometown.example.com
`, cli.AppHelpTemplate)
// EXAMPLE: Override a template
cli.AppHelpTemplate = `NAME:
{{.Name}} - {{.Usage}}
USAGE:
{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command
[command options]{{end}} {{if
.ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
{{if len .Authors}}
AUTHOR(S):
{{range .Authors}}{{ . }}{{end}}
{{end}}{{if .Commands}}
COMMANDS:
{{range .Commands}}{{if not .HideHelp}} {{join .Names ", "}}{{ "\t"
}}{{.Usage}}{{ "\n" }}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS:
{{range .VisibleFlags}}{{.}}
{{end}}{{end}}{{if .Copyright }}
COPYRIGHT:
{{.Copyright}}
{{end}}{{if .Version}}
VERSION:
{{.Version}}
{{end}}
`
// EXAMPLE: Replace the `HelpPrinter` func
cli.HelpPrinter = func(w io.Writer, templ string, data interface{}) {
fmt.Println("Ha HA. I pwnd the help!!1")
}
cli.NewApp().Run(os.Args)
}
```
## Contribution Guidelines
Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch.
If you have contributed something significant to the project, I will most likely add you as a collaborator. As a collaborator you are given the ability to merge others pull requests. It is very important that new code does not break existing code, so be careful about what code you do choose to merge. If you have any questions feel free to link @codegangsta to the issue in question and we can review it together.
If you feel like you have contributed to the project but have not yet been added as a collaborator, I probably forgot to add you. Hit @codegangsta up over email and we will get it figured out.

View file

@ -1,16 +0,0 @@
version: "{build}"
os: Windows Server 2012 R2
install:
- go version
- go env
build_script:
- cd %APPVEYOR_BUILD_FOLDER%
- go vet ./...
- go test -v ./...
test: off
deploy: off

View file

@ -1,262 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build ignore
package natspec
import (
"bytes"
"encoding/json"
"fmt"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/httpclient"
"github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/xeth"
"github.com/robertkrimen/otto"
)
type abi2method map[[8]byte]*method
type NatSpec struct {
jsvm *otto.Otto
abiDocJson []byte
userDoc userDoc
tx, data string
}
// main entry point for to get natspec notice for a transaction
// the implementation is frontend friendly in that it always gives back
// a notice that is safe to display
// :FIXME: the second return value is an error, which can be used to fine-tune bahaviour
func GetNotice(xeth *xeth.XEth, tx string, http *httpclient.HTTPClient) (notice string) {
ns, err := New(xeth, tx, http)
if err != nil {
if ns == nil {
return getFallbackNotice(fmt.Sprintf("no NatSpec info found for contract: %v", err), tx)
} else {
return getFallbackNotice(fmt.Sprintf("invalid NatSpec info: %v", err), tx)
}
}
notice, err = ns.Notice()
if err != nil {
return getFallbackNotice(fmt.Sprintf("NatSpec notice error: %v", err), tx)
}
return
}
func getFallbackNotice(comment, tx string) string {
return fmt.Sprintf("About to submit transaction (%s): %s", comment, tx)
}
type transaction struct {
To string `json:"to"`
Data string `json:"data"`
}
type jsonTx struct {
Params []transaction `json:"params"`
}
type contractInfo struct {
Source string `json:"source"`
Language string `json:"language"`
Version string `json:"compilerVersion"`
AbiDefinition json.RawMessage `json:"abiDefinition"`
UserDoc userDoc `json:"userDoc"`
DeveloperDoc json.RawMessage `json:"developerDoc"`
}
func New(xeth *xeth.XEth, jsontx string, http *httpclient.HTTPClient) (self *NatSpec, err error) {
// extract contract address from tx
var tx jsonTx
err = json.Unmarshal([]byte(jsontx), &tx)
if err != nil {
return
}
t := tx.Params[0]
contractAddress := t.To
content, err := FetchDocsForContract(contractAddress, xeth, http)
if err != nil {
return
}
self, err = NewWithDocs(content, jsontx, t.Data)
return
}
// also called by admin.contractInfo.get
func FetchDocsForContract(contractAddress string, xeth *xeth.XEth, client *httpclient.HTTPClient) (content []byte, err error) {
// retrieve contract hash from state
codehex := xeth.CodeAt(contractAddress)
codeb := xeth.CodeAtBytes(contractAddress)
if codehex == "0x" {
err = fmt.Errorf("contract (%v) not found", contractAddress)
return
}
codehash := common.BytesToHash(crypto.Keccak256(codeb))
// set up nameresolver with natspecreg + urlhint contract addresses
reg := registrar.New(xeth)
// resolve host via HashReg/UrlHint Resolver
hash, err := reg.HashToHash(codehash)
if err != nil {
return
}
if client.HasScheme("bzz") {
content, err = client.Get("bzz://"+hash.Hex()[2:], "")
if err == nil { // non-fatal
return
}
err = nil
//falling back to urlhint
}
uri, err := reg.HashToUrl(hash)
if err != nil {
return
}
// get content via http client and authenticate content using hash
content, err = client.GetAuthContent(uri, hash)
if err != nil {
return
}
return
}
func NewWithDocs(infoDoc []byte, tx string, data string) (self *NatSpec, err error) {
var contract contractInfo
err = json.Unmarshal(infoDoc, &contract)
if err != nil {
return
}
self = &NatSpec{
jsvm: otto.New(),
abiDocJson: []byte(contract.AbiDefinition),
userDoc: contract.UserDoc,
tx: tx,
data: data,
}
// load and require natspec js (but it is meant to be protected environment)
_, err = self.jsvm.Run(natspecJS)
if err != nil {
return
}
_, err = self.jsvm.Run("var natspec = require('natspec');")
return
}
// type abiDoc []method
// type method struct {
// Name string `json:name`
// Inputs []input `json:inputs`
// abiKey [8]byte
// }
// type input struct {
// Name string `json:name`
// Type string `json:type`
// }
// json skeleton for abi doc (contract method definitions)
type method struct {
Notice string `json:notice`
name string
}
type userDoc struct {
Methods map[string]*method `json:methods`
}
func (self *NatSpec) makeAbi2method(abiKey [8]byte) (meth *method) {
for signature, m := range self.userDoc.Methods {
name := strings.Split(signature, "(")[0]
hash := []byte(common.Bytes2Hex(crypto.Keccak256([]byte(signature))))
var key [8]byte
copy(key[:], hash[:8])
if bytes.Equal(key[:], abiKey[:]) {
meth = m
meth.name = name
return
}
}
return
}
func (self *NatSpec) Notice() (notice string, err error) {
var abiKey [8]byte
if len(self.data) < 10 {
err = fmt.Errorf("Invalid transaction data")
return
}
copy(abiKey[:], self.data[2:10])
meth := self.makeAbi2method(abiKey)
if meth == nil {
err = fmt.Errorf("abi key does not match any method")
return
}
notice, err = self.noticeForMethod(self.tx, meth.name, meth.Notice)
return
}
func (self *NatSpec) noticeForMethod(tx string, name, expression string) (notice string, err error) {
if _, err = self.jsvm.Run("var transaction = " + tx + ";"); err != nil {
return "", fmt.Errorf("natspec.js error setting transaction: %v", err)
}
if _, err = self.jsvm.Run("var abi = " + string(self.abiDocJson) + ";"); err != nil {
return "", fmt.Errorf("natspec.js error setting abi: %v", err)
}
if _, err = self.jsvm.Run("var method = '" + name + "';"); err != nil {
return "", fmt.Errorf("natspec.js error setting method: %v", err)
}
if _, err = self.jsvm.Run("var expression = \"" + expression + "\";"); err != nil {
return "", fmt.Errorf("natspec.js error setting expression: %v", err)
}
self.jsvm.Run("var call = {method: method,abi: abi,transaction: transaction};")
value, err := self.jsvm.Run("natspec.evaluateExpression(expression, call);")
if err != nil {
return "", fmt.Errorf("natspec.js error evaluating expression: %v", err)
}
evalError := "Natspec evaluation failed, wrong input params"
if value.String() == evalError {
return "", fmt.Errorf("natspec.js error evaluating expression: wrong input params in expression '%s'", expression)
}
if len(value.String()) == 0 {
return "", fmt.Errorf("natspec.js error evaluating expression")
}
return value.String(), nil
}

View file

@ -1,357 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build ignore
package natspec
import (
"fmt"
"io/ioutil"
"math/big"
"os"
"path/filepath"
"runtime"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/httpclient"
"github.com/ethereum/go-ethereum/common/registrar"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/node"
xe "github.com/ethereum/go-ethereum/xeth"
)
const (
testAddress = "0x8605cdbbdb6d264aa742e77020dcbc58fcdce182"
testBalance = "10000000000000000000"
testKey = "e6fab74a43941f82d89cb7faa408e227cdad3153c4720e540e855c19b15e6674"
testFileName = "long_file_name_for_testing_registration_of_URLs_longer_than_32_bytes.content"
testNotice = "Register key `utils.toHex(_key)` <- content `utils.toHex(_content)`"
testExpNotice = "Register key 0xadd1a7d961cff0242089674ec2ef6fca671ab15e1fe80e38859fc815b98d88ab <- content 0xb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7"
testExpNotice2 = `About to submit transaction (NatSpec notice error: abi key does not match any method): {"params":[{"to":"%s","data": "0x31e12c20"}]}`
testExpNotice3 = `About to submit transaction (no NatSpec info found for contract: HashToHash: content hash not found for '0x1392c62d05b2d149e22a339c531157ae06b44d39a674cce500064b12b9aeb019'): {"params":[{"to":"%s","data": "0x300a3bbfb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066696c653a2f2f2f746573742e636f6e74656e74"}]}`
)
const (
testUserDoc = `
{
"methods": {
"register(uint256,uint256)": {
"notice": "` + testNotice + `"
}
},
"invariants": [
{ "notice": "" }
],
"construction": [
{ "notice": "" }
]
}
`
testAbiDefinition = `
[{
"name": "register",
"constant": false,
"type": "function",
"inputs": [{
"name": "_key",
"type": "uint256"
}, {
"name": "_content",
"type": "uint256"
}],
"outputs": []
}]
`
testContractInfo = `
{
"userDoc": ` + testUserDoc + `,
"abiDefinition": ` + testAbiDefinition + `
}
`
)
type testFrontend struct {
t *testing.T
ethereum *eth.Ethereum
xeth *xe.XEth
wait chan *big.Int
lastConfirm string
wantNatSpec bool
}
func (self *testFrontend) AskPassword() (string, bool) {
return "", true
}
func (self *testFrontend) UnlockAccount(acc []byte) bool {
self.ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "password")
return true
}
func (self *testFrontend) ConfirmTransaction(tx string) bool {
if self.wantNatSpec {
client := httpclient.New("/tmp/")
self.lastConfirm = GetNotice(self.xeth, tx, client)
}
return true
}
func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) {
tmp, err := ioutil.TempDir("", "natspec-test")
if err != nil {
t.Fatal(err)
}
db, _ := ethdb.NewMemDatabase()
addr := common.HexToAddress(testAddress)
core.WriteGenesisBlockForTesting(db, core.GenesisAccount{addr, common.String2Big(testBalance)})
ks := crypto.NewKeyStorePassphrase(filepath.Join(tmp, "keystore"), crypto.LightScryptN, crypto.LightScryptP)
am := accounts.NewManager(ks)
keyb, err := crypto.HexToECDSA(testKey)
if err != nil {
t.Fatal(err)
}
key := crypto.NewKeyFromECDSA(keyb)
err = ks.StoreKey(key, "")
if err != nil {
t.Fatal(err)
}
err = am.Unlock(key.Address, "")
if err != nil {
t.Fatal(err)
}
// only use minimalistic stack with no networking
return eth.New(&node.ServiceContext{EventMux: new(event.TypeMux)}, &eth.Config{
AccountManager: am,
Etherbase: common.HexToAddress(testAddress),
PowTest: true,
TestGenesisState: db,
GpoMinGasPrice: common.Big1,
GpobaseCorrectionFactor: 1,
GpoMaxGasPrice: common.Big1,
})
}
func testInit(t *testing.T) (self *testFrontend) {
// initialise and start minimal ethereum stack
ethereum, err := testEth(t)
if err != nil {
t.Errorf("error creating ethereum: %v", err)
return
}
err = ethereum.Start(nil)
if err != nil {
t.Errorf("error starting ethereum: %v", err)
return
}
// mock frontend
self = &testFrontend{t: t, ethereum: ethereum}
self.xeth = xe.New(nil, self)
self.wait = self.xeth.UpdateState()
addr, _ := self.ethereum.Etherbase()
// initialise the registry contracts
reg := registrar.New(self.xeth)
registrar.GlobalRegistrarAddr = "0x0"
var txG, txH, txU string
txG, err = reg.SetGlobalRegistrar("", addr)
if err != nil {
t.Fatalf("error creating GlobalRegistrar: %v", err)
}
if !processTxs(self, t, 1) {
t.Fatalf("error mining txs")
}
recG := self.xeth.GetTxReceipt(common.HexToHash(txG))
if recG == nil {
t.Fatalf("blockchain error creating GlobalRegistrar")
}
registrar.GlobalRegistrarAddr = recG.ContractAddress.Hex()
txH, err = reg.SetHashReg("", addr)
if err != nil {
t.Errorf("error creating HashReg: %v", err)
}
if !processTxs(self, t, 1) {
t.Errorf("error mining txs")
}
recH := self.xeth.GetTxReceipt(common.HexToHash(txH))
if recH == nil {
t.Fatalf("blockchain error creating HashReg")
}
registrar.HashRegAddr = recH.ContractAddress.Hex()
txU, err = reg.SetUrlHint("", addr)
if err != nil {
t.Errorf("error creating UrlHint: %v", err)
}
if !processTxs(self, t, 1) {
t.Errorf("error mining txs")
}
recU := self.xeth.GetTxReceipt(common.HexToHash(txU))
if recU == nil {
t.Fatalf("blockchain error creating UrlHint")
}
registrar.UrlHintAddr = recU.ContractAddress.Hex()
return
}
// end to end test
func TestNatspecE2E(t *testing.T) {
t.Skip()
tf := testInit(t)
defer tf.ethereum.Stop()
addr, _ := tf.ethereum.Etherbase()
// create a contractInfo file (mock cloud-deployed contract metadocs)
// incidentally this is the info for the HashReg contract itself
ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm)
dochash := crypto.Keccak256Hash([]byte(testContractInfo))
// take the codehash for the contract we wanna test
codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr)
codehash := crypto.Keccak256Hash(codeb)
reg := registrar.New(tf.xeth)
_, err := reg.SetHashToHash(addr, codehash, dochash)
if err != nil {
t.Errorf("error registering: %v", err)
}
_, err = reg.SetUrlToHash(addr, dochash, "file:///"+testFileName)
if err != nil {
t.Errorf("error registering: %v", err)
}
if !processTxs(tf, t, 5) {
return
}
// NatSpec info for register method of HashReg contract installed
// now using the same transactions to check confirm messages
tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation
_, err = reg.SetHashToHash(addr, codehash, dochash)
if err != nil {
t.Errorf("error calling contract registry: %v", err)
}
fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr)
if tf.lastConfirm != testExpNotice {
t.Errorf("Wrong confirm message. expected\n'%v', got\n'%v'", testExpNotice, tf.lastConfirm)
}
// test unknown method
exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr)
_, err = reg.SetOwner(addr)
if err != nil {
t.Errorf("error setting owner: %v", err)
}
if tf.lastConfirm != exp {
t.Errorf("Wrong confirm message, expected\n'%v', got\n'%v'", exp, tf.lastConfirm)
}
// test unknown contract
exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr)
_, err = reg.SetUrlToHash(addr, dochash, "file:///test.content")
if err != nil {
t.Errorf("error registering: %v", err)
}
if tf.lastConfirm != exp {
t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm)
}
}
func pendingTransactions(repl *testFrontend, t *testing.T) (txc int64, err error) {
txs := repl.ethereum.TxPool().GetTransactions()
return int64(len(txs)), nil
}
func processTxs(repl *testFrontend, t *testing.T, expTxc int) bool {
var txc int64
var err error
for i := 0; i < 50; i++ {
txc, err = pendingTransactions(repl, t)
if err != nil {
t.Errorf("unexpected error checking pending transactions: %v", err)
return false
}
if expTxc < int(txc) {
t.Errorf("too many pending transactions: expected %v, got %v", expTxc, txc)
return false
} else if expTxc == int(txc) {
break
}
time.Sleep(100 * time.Millisecond)
}
if int(txc) != expTxc {
t.Errorf("incorrect number of pending transactions, expected %v, got %v", expTxc, txc)
return false
}
err = repl.ethereum.StartMining(runtime.NumCPU(), "")
if err != nil {
t.Errorf("unexpected error mining: %v", err)
return false
}
defer repl.ethereum.StopMining()
timer := time.NewTimer(100 * time.Second)
height := new(big.Int).Add(repl.xeth.CurrentBlock().Number(), big.NewInt(1))
repl.wait <- height
select {
case <-timer.C:
// if times out make sure the xeth loop does not block
go func() {
select {
case repl.wait <- nil:
case <-repl.wait:
}
}()
case <-repl.wait:
}
txc, err = pendingTransactions(repl, t)
if err != nil {
t.Errorf("unexpected error checking pending transactions: %v", err)
return false
}
if txc != 0 {
t.Errorf("%d trasactions were not mined", txc)
return false
}
return true
}

File diff suppressed because one or more lines are too long

View file

@ -1,160 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// +build ignore
package natspec
import (
"testing"
)
func makeInfoDoc(desc string) []byte {
return []byte(`
{
"source": "contract test { }",
"language": "Solidity",
"compilerVersion": "1",
"userDoc": {
"methods": {
"multiply(uint256)": {
"notice": "` + desc + `"
},
"balance(address)": {
"notice": "` + "`(balanceInmGAV / 1000).fixed(0,3)`" + ` GAV is the total funds available to ` + "`who.address()`." + `"
}
},
"invariants": [
{ "notice": "The sum total amount of GAV in the system is 1 million." }
],
"construction": [
{ "notice": "Endows ` + "`message.caller.address()`" + ` with 1m GAV." }
]
},
"abiDefinition": [{
"name": "multiply",
"constant": false,
"type": "function",
"inputs": [{
"name": "a",
"type": "uint256"
}],
"outputs": [{
"name": "d",
"type": "uint256"
}]
}]
}`)
}
var data = "0xc6888fa1000000000000000000000000000000000000000000000000000000000000007a"
var tx = `
{
"params": [{
"to": "0x8521742d3f456bd237e312d6e30724960f72517a",
"data": "0xc6888fa1000000000000000000000000000000000000000000000000000000000000007a"
}],
}
`
func TestNotice(t *testing.T) {
desc := "Will multiply `a` by 7 and return `a * 7`."
expected := "Will multiply 122 by 7 and return 854."
infodoc := makeInfoDoc(desc)
ns, err := NewWithDocs(infodoc, tx, data)
if err != nil {
t.Errorf("New: error: %v", err)
return
}
notice, err := ns.Notice()
if err != nil {
t.Errorf("expected no error, got %v", err)
}
if notice != expected {
t.Errorf("incorrect notice. expected %v, got %v", expected, notice)
}
}
// test missing method
func TestMissingMethod(t *testing.T) {
desc := "Will multiply `a` by 7 and return `a * 7`."
expected := "natspec.js error evaluating expression: Natspec evaluation failed, method does not exist"
infodoc := makeInfoDoc(desc)
ns, err := NewWithDocs(infodoc, tx, data)
if err != nil {
t.Errorf("New: error: %v", err)
}
notice, err := ns.noticeForMethod(tx, "missing_method", "")
if err == nil {
t.Errorf("expected error, got nothing (notice: '%v')", notice)
} else {
if err.Error() != expected {
t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
}
}
}
// test invalid desc
func TestInvalidDesc(t *testing.T) {
desc := "Will multiply 122 by \"7\" and return 854."
expected := "invalid character '7' after object key:value pair"
infodoc := makeInfoDoc(desc)
_, err := NewWithDocs(infodoc, tx, data)
if err == nil {
t.Errorf("expected error, got nothing", err)
} else {
if err.Error() != expected {
t.Errorf("expected error '%s' got '%v'", expected, err)
}
}
}
// test wrong input params
func TestWrongInputParams(t *testing.T) {
desc := "Will multiply `e` by 7 and return `a * 7`."
expected := "natspec.js error evaluating expression: Natspec evaluation failed, wrong input params"
infodoc := makeInfoDoc(desc)
ns, err := NewWithDocs(infodoc, tx, data)
if err != nil {
t.Errorf("New: error: %v", err)
}
notice, err := ns.Notice()
if err == nil {
t.Errorf("expected error, got nothing (notice: '%v')", notice)
} else {
if err.Error() != expected {
t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
}
}
}

37
vendor.conf Normal file
View file

@ -0,0 +1,37 @@
# package
github.com/ethereum/go-ethereum
github.com/Gustav-Simonsson/go-opencl 593e01c
github.com/cespare/cp 165db2f
github.com/davecgh/go-spew v1.0.0-3-g6d21280
github.com/ethereum/ethash v23.1-247-g2e80de5
github.com/fatih/color v1.1.0-1-ga360acf
github.com/gizak/termui a7e3aee
github.com/golang/snappy d9eb7a3
github.com/hashicorp/golang-lru 0a025b7
github.com/huin/goupnp d7ddae7
github.com/jackpal/go-nat-pmp v1.0.1-4-g1fa385a
github.com/mattn/go-colorable v0.0.6-6-g6c903ff
github.com/mattn/go-isatty 66b8e73
github.com/mattn/go-runewidth v0.0.1-10-g737072b
github.com/mitchellh/go-wordwrap ad45545
github.com/nsf/termbox-go b6acae5
github.com/pborman/uuid v1.0-17-g3d4f2ba
github.com/peterh/liner 8975875
github.com/rcrowley/go-metrics ab2277b
github.com/rjeczalik/notify 7e20c15
github.com/robertkrimen/otto bf1c379
github.com/rs/cors v1.0
github.com/rs/xhandler v1.0-1-ged27b6f
github.com/syndtr/goleveldb 6b4daa5
golang.org/x/crypto 3c0d69f
golang.org/x/net 5695785
golang.org/x/sys c200b10
golang.org/x/text 5a42fa2
golang.org/x/tools c6efba0
gopkg.in/check.v1 4f90aea
gopkg.in/fatih/set.v0 v0.1.0-3-g27c4092
gopkg.in/karalabe/cookiejar.v2 8dcd6a7
gopkg.in/natefinch/npipe.v2 c1b8fa8
gopkg.in/sourcemap.v1 v1.0.3
gopkg.in/urfave/cli.v1 v1.18.1

View file

@ -0,0 +1,8 @@
OpenCL bindings for Go
======================
Documentation at <http://godoc.org/github.com/samuel/go-opencl/cl>
Can look at cl_test.go for an example of use.
To get OpenCL 1.2 API build with the tag `cl12`

14
vendor/github.com/davecgh/go-spew/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,14 @@
language: go
go:
- 1.5.4
- 1.6.3
- 1.7
install:
- go get -v golang.org/x/tools/cmd/cover
script:
- go test -v -tags=safe ./spew
- go test -v -tags=testcgo ./spew -covermode=count -coverprofile=profile.cov
after_success:
- go get -v github.com/mattn/goveralls
- export PATH=$PATH:$HOME/gopath/bin
- goveralls -coverprofile=profile.cov -service=travis-ci

View file

@ -1,3 +1,5 @@
ISC License
Copyright (c) 2012-2013 Dave Collins <dave@davec.name> Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
Permission to use, copy, modify, and distribute this software for any Permission to use, copy, modify, and distribute this software for any

194
vendor/github.com/davecgh/go-spew/README.md generated vendored Normal file
View file

@ -0,0 +1,194 @@
go-spew
=======
[![Build Status](https://travis-ci.org/davecgh/go-spew.png?branch=master)]
(https://travis-ci.org/davecgh/go-spew) [![Coverage Status]
(https://coveralls.io/repos/davecgh/go-spew/badge.png?branch=master)]
(https://coveralls.io/r/davecgh/go-spew?branch=master)
Go-spew implements a deep pretty printer for Go data structures to aid in
debugging. A comprehensive suite of tests with 100% test coverage is provided
to ensure proper functionality. See `test_coverage.txt` for the gocov coverage
report. Go-spew is licensed under the liberal ISC license, so it may be used in
open source or commercial projects.
If you're interested in reading about how this package came to life and some
of the challenges involved in providing a deep pretty printer, there is a blog
post about it
[here](https://web.archive.org/web/20160304013555/https://blog.cyphertite.com/go-spew-a-journey-into-dumping-go-data-structures/).
## Documentation
[![GoDoc](https://godoc.org/github.com/davecgh/go-spew/spew?status.png)]
(http://godoc.org/github.com/davecgh/go-spew/spew)
Full `go doc` style documentation for the project can be viewed online without
installing this package by using the excellent GoDoc site here:
http://godoc.org/github.com/davecgh/go-spew/spew
You can also view the documentation locally once the package is installed with
the `godoc` tool by running `godoc -http=":6060"` and pointing your browser to
http://localhost:6060/pkg/github.com/davecgh/go-spew/spew
## Installation
```bash
$ go get -u github.com/davecgh/go-spew/spew
```
## Quick Start
Add this import line to the file you're working in:
```Go
import "github.com/davecgh/go-spew/spew"
```
To dump a variable with full newlines, indentation, type, and pointer
information use Dump, Fdump, or Sdump:
```Go
spew.Dump(myVar1, myVar2, ...)
spew.Fdump(someWriter, myVar1, myVar2, ...)
str := spew.Sdump(myVar1, myVar2, ...)
```
Alternatively, if you would prefer to use format strings with a compacted inline
printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most
compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types
and pointer addresses):
```Go
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
```
## Debugging a Web Application Example
Here is an example of how you can use `spew.Sdump()` to help debug a web application. Please be sure to wrap your output using the `html.EscapeString()` function for safety reasons. You should also only use this debugging technique in a development environment, never in production.
```Go
package main
import (
"fmt"
"html"
"net/http"
"github.com/davecgh/go-spew/spew"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
fmt.Fprintf(w, "Hi there, %s!", r.URL.Path[1:])
fmt.Fprintf(w, "<!--\n" + html.EscapeString(spew.Sdump(w)) + "\n-->")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
```
## Sample Dump Output
```
(main.Foo) {
unexportedField: (*main.Bar)(0xf84002e210)({
flag: (main.Flag) flagTwo,
data: (uintptr) <nil>
}),
ExportedField: (map[interface {}]interface {}) {
(string) "one": (bool) true
}
}
([]uint8) {
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
00000020 31 32 |12|
}
```
## Sample Formatter Output
Double pointer to a uint8:
```
%v: <**>5
%+v: <**>(0xf8400420d0->0xf8400420c8)5
%#v: (**uint8)5
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
```
Pointer to circular struct with a uint8 field and a pointer to itself:
```
%v: <*>{1 <*><shown>}
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
```
## Configuration Options
Configuration of spew is handled by fields in the ConfigState type. For
convenience, all of the top-level functions use a global state available via the
spew.Config global.
It is also possible to create a ConfigState instance that provides methods
equivalent to the top-level functions. This allows concurrent configuration
options. See the ConfigState documentation for more details.
```
* Indent
String to use for each indentation level for Dump functions.
It is a single space by default. A popular alternative is "\t".
* MaxDepth
Maximum number of levels to descend into nested data structures.
There is no limit by default.
* DisableMethods
Disables invocation of error and Stringer interface methods.
Method invocation is enabled by default.
* DisablePointerMethods
Disables invocation of error and Stringer interface methods on types
which only accept pointer receivers from non-pointer variables. This option
relies on access to the unsafe package, so it will not have any effect when
running in environments without access to the unsafe package such as Google
App Engine or with the "safe" build tag specified.
Pointer method invocation is enabled by default.
* ContinueOnMethod
Enables recursion into types after invoking error and Stringer interface
methods. Recursion after method invocation is disabled by default.
* SortKeys
Specifies map keys should be sorted before being printed. Use
this to have a more deterministic, diffable output. Note that
only native types (bool, int, uint, floats, uintptr and string)
and types which implement error or Stringer interfaces are supported,
with other types sorted according to the reflect.Value.String() output
which guarantees display stability. Natural map order is used by
default.
* SpewKeys
SpewKeys specifies that, as a last resort attempt, map keys should be
spewed to strings and sorted by those strings. This is only considered
if SortKeys is true.
```
## Unsafe Package Dependency
This package relies on the unsafe package to perform some of the more advanced
features, however it also supports a "limited" mode which allows it to work in
environments where the unsafe package is not available. By default, it will
operate in this mode on Google App Engine and when compiled with GopherJS. The
"safe" build tag may also be specified to force the package to build without
using the unsafe package.
## License
Go-spew is licensed under the liberal ISC License.

22
vendor/github.com/davecgh/go-spew/cov_report.sh generated vendored Normal file
View file

@ -0,0 +1,22 @@
#!/bin/sh
# This script uses gocov to generate a test coverage report.
# The gocov tool my be obtained with the following command:
# go get github.com/axw/gocov/gocov
#
# It will be installed to $GOPATH/bin, so ensure that location is in your $PATH.
# Check for gocov.
if ! type gocov >/dev/null 2>&1; then
echo >&2 "This script requires the gocov tool."
echo >&2 "You may obtain it with the following command:"
echo >&2 "go get github.com/axw/gocov/gocov"
exit 1
fi
# Only run the cgo tests if gcc is installed.
if type gcc >/dev/null 2>&1; then
(cd spew && gocov test -tags testcgo | gocov report)
else
(cd spew && gocov test | gocov report)
fi

View file

@ -13,9 +13,10 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled // NOTE: Due to the following build constraints, this file will only be compiled
// when the code is not running on Google App Engine and "-tags disableunsafe" // when the code is not running on Google App Engine, compiled by GopherJS, and
// is not added to the go build command line. // "-tags safe" is not added to the go build command line. The "disableunsafe"
// +build !appengine,!disableunsafe // tag is deprecated and thus should not be used.
// +build !js,!appengine,!safe,!disableunsafe
package spew package spew

View file

@ -13,9 +13,10 @@
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled // NOTE: Due to the following build constraints, this file will only be compiled
// when either the code is running on Google App Engine or "-tags disableunsafe" // when the code is running on Google App Engine, compiled by GopherJS, or
// is added to the go build command line. // "-tags safe" is added to the go build command line. The "disableunsafe"
// +build appengine disableunsafe // tag is deprecated and thus should not be used.
// +build js appengine safe disableunsafe
package spew package spew

View file

@ -64,7 +64,7 @@ type ConfigState struct {
// inside these interface methods. As a result, this option relies on // inside these interface methods. As a result, this option relies on
// access to the unsafe package, so it will not have any effect when // access to the unsafe package, so it will not have any effect when
// running in environments without access to the unsafe package such as // running in environments without access to the unsafe package such as
// Google App Engine or with the "disableunsafe" build tag specified. // Google App Engine or with the "safe" build tag specified.
DisablePointerMethods bool DisablePointerMethods bool
// ContinueOnMethod specifies whether or not recursion should continue once // ContinueOnMethod specifies whether or not recursion should continue once

61
vendor/github.com/davecgh/go-spew/test_coverage.txt generated vendored Normal file
View file

@ -0,0 +1,61 @@
github.com/davecgh/go-spew/spew/dump.go dumpState.dump 100.00% (88/88)
github.com/davecgh/go-spew/spew/format.go formatState.format 100.00% (82/82)
github.com/davecgh/go-spew/spew/format.go formatState.formatPtr 100.00% (52/52)
github.com/davecgh/go-spew/spew/dump.go dumpState.dumpPtr 100.00% (44/44)
github.com/davecgh/go-spew/spew/dump.go dumpState.dumpSlice 100.00% (39/39)
github.com/davecgh/go-spew/spew/common.go handleMethods 100.00% (30/30)
github.com/davecgh/go-spew/spew/common.go printHexPtr 100.00% (18/18)
github.com/davecgh/go-spew/spew/common.go unsafeReflectValue 100.00% (13/13)
github.com/davecgh/go-spew/spew/format.go formatState.constructOrigFormat 100.00% (12/12)
github.com/davecgh/go-spew/spew/dump.go fdump 100.00% (11/11)
github.com/davecgh/go-spew/spew/format.go formatState.Format 100.00% (11/11)
github.com/davecgh/go-spew/spew/common.go init 100.00% (10/10)
github.com/davecgh/go-spew/spew/common.go printComplex 100.00% (9/9)
github.com/davecgh/go-spew/spew/common.go valuesSorter.Less 100.00% (8/8)
github.com/davecgh/go-spew/spew/format.go formatState.buildDefaultFormat 100.00% (7/7)
github.com/davecgh/go-spew/spew/format.go formatState.unpackValue 100.00% (5/5)
github.com/davecgh/go-spew/spew/dump.go dumpState.indent 100.00% (4/4)
github.com/davecgh/go-spew/spew/common.go catchPanic 100.00% (4/4)
github.com/davecgh/go-spew/spew/config.go ConfigState.convertArgs 100.00% (4/4)
github.com/davecgh/go-spew/spew/spew.go convertArgs 100.00% (4/4)
github.com/davecgh/go-spew/spew/format.go newFormatter 100.00% (3/3)
github.com/davecgh/go-spew/spew/dump.go Sdump 100.00% (3/3)
github.com/davecgh/go-spew/spew/common.go printBool 100.00% (3/3)
github.com/davecgh/go-spew/spew/common.go sortValues 100.00% (3/3)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sdump 100.00% (3/3)
github.com/davecgh/go-spew/spew/dump.go dumpState.unpackValue 100.00% (3/3)
github.com/davecgh/go-spew/spew/spew.go Printf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Println 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Sprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Sprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Sprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go printFloat 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go NewDefaultConfig 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go printInt 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go printUint 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go valuesSorter.Len 100.00% (1/1)
github.com/davecgh/go-spew/spew/common.go valuesSorter.Swap 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Errorf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Print 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Printf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Println 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Sprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.NewFormatter 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Fdump 100.00% (1/1)
github.com/davecgh/go-spew/spew/config.go ConfigState.Dump 100.00% (1/1)
github.com/davecgh/go-spew/spew/dump.go Fdump 100.00% (1/1)
github.com/davecgh/go-spew/spew/dump.go Dump 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Fprintln 100.00% (1/1)
github.com/davecgh/go-spew/spew/format.go NewFormatter 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Errorf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Fprint 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Fprintf 100.00% (1/1)
github.com/davecgh/go-spew/spew/spew.go Print 100.00% (1/1)
github.com/davecgh/go-spew/spew ------------------------------- 100.00% (505/505)

Some files were not shown because too many files have changed in this diff Show more