aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2017-01-11 02:33:17 +0800
committerFelix Lange <fjl@twurst.com>2017-01-11 05:33:24 +0800
commitd78f9b834ade0f1ebcf2532bf90d01c85ad50a8e (patch)
treedd03906433e1032a0b185910773206246d8a1556 /vendor/github.com
parent02b67558e8eaa7b34a28b8dd0223824bbbb52349 (diff)
downloadgo-tangerine-d78f9b834ade0f1ebcf2532bf90d01c85ad50a8e.tar.gz
go-tangerine-d78f9b834ade0f1ebcf2532bf90d01c85ad50a8e.tar.zst
go-tangerine-d78f9b834ade0f1ebcf2532bf90d01c85ad50a8e.zip
vendor: update all dependencies except Azure SDK
The Azure SDK doesn't support Go 1.5 anymore. We can't upgrade it until Go 1.8 comes out.
Diffstat (limited to 'vendor/github.com')
-rw-r--r--vendor/github.com/aristanetworks/goarista/.travis.yml3
-rw-r--r--vendor/github.com/aristanetworks/goarista/Dockerfile2
-rw-r--r--vendor/github.com/fatih/color/README.md21
-rw-r--r--vendor/github.com/fatih/color/color.go129
-rw-r--r--vendor/github.com/fatih/color/doc.go14
-rw-r--r--vendor/github.com/gizak/termui/barchart.go2
-rw-r--r--vendor/github.com/gizak/termui/block.go2
-rw-r--r--vendor/github.com/gizak/termui/block_common.go2
-rw-r--r--vendor/github.com/gizak/termui/block_windows.go2
-rw-r--r--vendor/github.com/gizak/termui/buffer.go6
-rw-r--r--vendor/github.com/gizak/termui/canvas.go2
-rwxr-xr-xvendor/github.com/gizak/termui/config26
-rw-r--r--vendor/github.com/gizak/termui/config.py79
-rw-r--r--vendor/github.com/gizak/termui/doc.go2
-rw-r--r--vendor/github.com/gizak/termui/events.go2
-rw-r--r--vendor/github.com/gizak/termui/gauge.go2
-rw-r--r--vendor/github.com/gizak/termui/glide.lock28
-rw-r--r--vendor/github.com/gizak/termui/glide.yaml1
-rw-r--r--vendor/github.com/gizak/termui/grid.go2
-rw-r--r--vendor/github.com/gizak/termui/helper.go2
-rw-r--r--vendor/github.com/gizak/termui/linechart.go2
-rw-r--r--vendor/github.com/gizak/termui/linechart_others.go2
-rw-r--r--vendor/github.com/gizak/termui/linechart_windows.go2
-rw-r--r--vendor/github.com/gizak/termui/list.go2
-rw-r--r--vendor/github.com/gizak/termui/mbarchart.go2
-rw-r--r--vendor/github.com/gizak/termui/par.go2
-rw-r--r--vendor/github.com/gizak/termui/pos.go2
-rw-r--r--vendor/github.com/gizak/termui/render.go33
-rw-r--r--vendor/github.com/gizak/termui/sparkline.go2
-rw-r--r--vendor/github.com/gizak/termui/table.go170
-rw-r--r--vendor/github.com/gizak/termui/textbuilder.go2
-rw-r--r--vendor/github.com/gizak/termui/theme.go2
-rw-r--r--vendor/github.com/gizak/termui/widget.go2
-rw-r--r--vendor/github.com/huin/goupnp/README.md18
-rw-r--r--vendor/github.com/maruel/panicparse/.travis.yml15
-rw-r--r--vendor/github.com/maruel/panicparse/LICENSE201
-rw-r--r--vendor/github.com/maruel/panicparse/README.md123
-rw-r--r--vendor/github.com/maruel/panicparse/stack/source.go291
-rw-r--r--vendor/github.com/maruel/panicparse/stack/stack.go832
-rw-r--r--vendor/github.com/maruel/panicparse/stack/ui.go139
-rw-r--r--vendor/github.com/maruel/panicparse/vendor.yml17
-rw-r--r--vendor/github.com/mattn/go-colorable/colorable_others.go3
-rw-r--r--vendor/github.com/mattn/go-colorable/colorable_windows.go4
-rw-r--r--vendor/github.com/mattn/go-colorable/noncolorable.go3
-rw-r--r--vendor/github.com/nsf/termbox-go/README.md1
-rw-r--r--vendor/github.com/nsf/termbox-go/api.go1
-rw-r--r--vendor/github.com/nsf/termbox-go/termbox.go5
-rw-r--r--vendor/github.com/pborman/uuid/README.md2
-rw-r--r--vendor/github.com/rcrowley/go-metrics/gauge.go4
-rw-r--r--vendor/github.com/rcrowley/go-metrics/registry.go6
-rw-r--r--vendor/github.com/rcrowley/go-metrics/sample.go9
-rw-r--r--vendor/github.com/syndtr/goleveldb/leveldb/session.go2
-rw-r--r--vendor/github.com/syndtr/goleveldb/leveldb/session_util.go27
-rw-r--r--vendor/github.com/syndtr/goleveldb/leveldb/version.go40
54 files changed, 2170 insertions, 127 deletions
diff --git a/vendor/github.com/aristanetworks/goarista/.travis.yml b/vendor/github.com/aristanetworks/goarista/.travis.yml
index 534f444ca..1f34efa6b 100644
--- a/vendor/github.com/aristanetworks/goarista/.travis.yml
+++ b/vendor/github.com/aristanetworks/goarista/.travis.yml
@@ -1,6 +1,6 @@
language: go
go:
-- 1.6.2
+- 1.7.3
- tip
before_install:
- go get -v github.com/golang/lint/golint
@@ -13,3 +13,4 @@ script:
notifications:
slack:
secure: MO/3LqbyALbi9vAY3pZetp/LfRuKEPAYEUya7XKmTWA3OFHYkTGqJWNosVkFJd6eSKwnc3HP4jlKADEBNVxADHzcA3uMPUQi1mIcNk/Ps1WWMNDv1liE2XOoOmHSHZ/8ksk6TNq83x+d17ZffYq8KAH6iKNKvllO1JzQPgJJdf+cNXQQlg6uPSe+ggMpjqVLkKcHqA4L3/BWo6fNcyvkqaN3uXcEzYPi7Nb2q9tl0ja6ToyZV4H6SinwitZmpedN3RkBcm4fKmGyw5ikzH93ycA5SvWrnXTh1dJvq6DU0FV7iwI6oqPTbAUc3FE5g7aEkK0qVR21s2j+KNaOLnuX10ZGQFwj2r3SW2REHq4j+qqFla/2EmSFZJt3GXYS+plmGCxqCgyjSw6tTi7LaGZ/mWBJEA9/EaXG1NkwlQYx5tdUMeGj77OczjXClynpb2hJ7MM2b32Rnp0JmNaXAh01SmClo+8nDWuksAsIdPtWsbF0/XHmEJiqpu8ojvVXOQIbPt43bjG7PS1t5jaRAU/N1n56SiCGgCSGd3Ui5eX5vmgWdpZMl8NG05G4LFsgmkdphRT5fru0C2PrhNZYRDGWs63XKapBxsvfqGzdHxTtYuaDjHjrI+9w0BC/8kEzSWoPmabQ5ci4wf4DeplcIay4tDMgMSo8pGAf52vrne4rmUo=
+ on_success: change
diff --git a/vendor/github.com/aristanetworks/goarista/Dockerfile b/vendor/github.com/aristanetworks/goarista/Dockerfile
index e8a0f4179..0322e564e 100644
--- a/vendor/github.com/aristanetworks/goarista/Dockerfile
+++ b/vendor/github.com/aristanetworks/goarista/Dockerfile
@@ -3,7 +3,7 @@
# that can be found in the COPYING file.
# TODO: move this to cmd/ockafka (https://github.com/docker/hub-feedback/issues/292)
-FROM golang:1.6
+FROM golang:1.7.3
RUN mkdir -p /go/src/github.com/aristanetworks/goarista/cmd
WORKDIR /go/src/github.com/aristanetworks/goarista
diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md
index 6e39e919f..7c8eea20e 100644
--- a/vendor/github.com/fatih/color/README.md
+++ b/vendor/github.com/fatih/color/README.md
@@ -56,6 +56,16 @@ whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with white background.")
```
+### Use your own output (io.Writer)
+
+```go
+// Use your own io.Writer output
+color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
+
+blue := color.New(color.FgBlue)
+blue.Fprint(writer, "This will print text in blue.")
+```
+
### Custom print functions (PrintFunc)
```go
@@ -69,6 +79,17 @@ notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("Don't forget this...")
```
+### Custom fprint functions (FprintFunc)
+
+```go
+blue := color.New(FgBlue).FprintfFunc()
+blue(myWriter, "important notice: %s", stars)
+
+// Mix up with multiple attributes
+success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
+success(myWriter, don't forget this...")
+```
+
### Insert into noncolor strings (SprintFunc)
```go
diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go
index 06f4867f7..dba8f211e 100644
--- a/vendor/github.com/fatih/color/color.go
+++ b/vendor/github.com/fatih/color/color.go
@@ -2,6 +2,7 @@ package color
import (
"fmt"
+ "io"
"os"
"strconv"
"strings"
@@ -11,11 +12,22 @@ import (
"github.com/mattn/go-isatty"
)
-// NoColor defines if the output is colorized or not. It's dynamically set to
-// false or true based on the stdout's file descriptor referring to a terminal
-// or not. This is a global option and affects all colors. For more control
-// over each color block use the methods DisableColor() individually.
-var NoColor = !isatty.IsTerminal(os.Stdout.Fd())
+var (
+ // NoColor defines if the output is colorized or not. It's dynamically set to
+ // false or true based on the stdout's file descriptor referring to a terminal
+ // or not. This is a global option and affects all colors. For more control
+ // over each color block use the methods DisableColor() individually.
+ NoColor = !isatty.IsTerminal(os.Stdout.Fd()) || os.Getenv("TERM") == "dumb"
+
+ // Output defines the standard output of the print functions. By default
+ // os.Stdout is used.
+ Output = colorable.NewColorableStdout()
+
+ // colorsCache is used to reduce the count of created Color objects and
+ // allows to reuse already created objects with required Attribute.
+ colorsCache = make(map[Attribute]*Color)
+ colorsCacheMu sync.Mutex // protects colorsCache
+)
// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
@@ -133,6 +145,27 @@ func (c *Color) unset() {
Unset()
}
+func (c *Color) setWriter(w io.Writer) *Color {
+ if c.isNoColorSet() {
+ return c
+ }
+
+ fmt.Fprintf(w, c.format())
+ return c
+}
+
+func (c *Color) unsetWriter(w io.Writer) {
+ if c.isNoColorSet() {
+ return
+ }
+
+ if NoColor {
+ return
+ }
+
+ fmt.Fprintf(w, "%s[%dm", escape, Reset)
+}
+
// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attribute) *Color {
@@ -146,9 +179,17 @@ func (c *Color) prepend(value Attribute) {
c.params[0] = value
}
-// Output defines the standard output of the print functions. By default
-// os.Stdout is used.
-var Output = colorable.NewColorableStdout()
+// Fprint formats using the default formats for its operands and writes to w.
+// Spaces are added between operands when neither is a string.
+// It returns the number of bytes written and any write error encountered.
+// On Windows, users should wrap w with colorable.NewColorable() if w is of
+// type *os.File.
+func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
+ c.setWriter(w)
+ defer c.unsetWriter(w)
+
+ return fmt.Fprint(w, a...)
+}
// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
@@ -162,6 +203,17 @@ func (c *Color) Print(a ...interface{}) (n int, err error) {
return fmt.Fprint(Output, a...)
}
+// Fprintf formats according to a format specifier and writes to w.
+// It returns the number of bytes written and any write error encountered.
+// On Windows, users should wrap w with colorable.NewColorable() if w is of
+// type *os.File.
+func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
+ c.setWriter(w)
+ defer c.unsetWriter(w)
+
+ return fmt.Fprintf(w, format, a...)
+}
+
// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
@@ -172,6 +224,17 @@ func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
return fmt.Fprintf(Output, format, a...)
}
+// Fprintln formats using the default formats for its operands and writes to w.
+// Spaces are always added between operands and a newline is appended.
+// On Windows, users should wrap w with colorable.NewColorable() if w is of
+// type *os.File.
+func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
+ c.setWriter(w)
+ defer c.unsetWriter(w)
+
+ return fmt.Fprintln(w, a...)
+}
+
// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
@@ -184,27 +247,57 @@ func (c *Color) Println(a ...interface{}) (n int, err error) {
return fmt.Fprintln(Output, a...)
}
+// FprintFunc returns a new function that prints the passed arguments as
+// colorized with color.Fprint().
+func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
+ return func(w io.Writer, a ...interface{}) {
+ c.Fprint(w, a...)
+ }
+}
+
// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
- return func(a ...interface{}) { c.Print(a...) }
+ return func(a ...interface{}) {
+ c.Print(a...)
+ }
+}
+
+// FprintfFunc returns a new function that prints the passed arguments as
+// colorized with color.Fprintf().
+func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
+ return func(w io.Writer, format string, a ...interface{}) {
+ c.Fprintf(w, format, a...)
+ }
}
// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
- return func(format string, a ...interface{}) { c.Printf(format, a...) }
+ return func(format string, a ...interface{}) {
+ c.Printf(format, a...)
+ }
+}
+
+// FprintlnFunc returns a new function that prints the passed arguments as
+// colorized with color.Fprintln().
+func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
+ return func(w io.Writer, a ...interface{}) {
+ c.Fprintln(w, a...)
+ }
}
// PrintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Println().
func (c *Color) PrintlnFunc() func(a ...interface{}) {
- return func(a ...interface{}) { c.Println(a...) }
+ return func(a ...interface{}) {
+ c.Println(a...)
+ }
}
// SprintFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprint(). Useful to put into or mix into other
-// string. Windows users should use this in conjuction with color.Output, example:
+// string. Windows users should use this in conjunction with color.Output, example:
//
// put := New(FgYellow).SprintFunc()
// fmt.Fprintf(color.Output, "This is a %s", put("warning"))
@@ -216,7 +309,7 @@ func (c *Color) SprintFunc() func(a ...interface{}) string {
// SprintfFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
-// string. Windows users should use this in conjuction with color.Output.
+// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
return func(format string, a ...interface{}) string {
return c.wrap(fmt.Sprintf(format, a...))
@@ -225,7 +318,7 @@ func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
// SprintlnFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
-// string. Windows users should use this in conjuction with color.Output.
+// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
return func(a ...interface{}) string {
return c.wrap(fmt.Sprintln(a...))
@@ -268,7 +361,7 @@ func (c *Color) DisableColor() {
c.noColor = boolPtr(true)
}
-// EnableColor enables the color output. Use it in conjuction with
+// EnableColor enables the color output. Use it in conjunction with
// DisableColor(). Otherwise this method has no side effects.
func (c *Color) EnableColor() {
c.noColor = boolPtr(false)
@@ -313,12 +406,6 @@ func boolPtr(v bool) *bool {
return &v
}
-// colorsCache is used to reduce the count of created Color objects and
-// allows to reuse already created objects with required Attribute.
-var colorsCache = make(map[Attribute]*Color)
-
-var colorsCacheMu = new(sync.Mutex) // protects colorsCache
-
func getCachedColor(p Attribute) *Color {
colorsCacheMu.Lock()
defer colorsCacheMu.Unlock()
diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go
index 17908787c..1e57812d7 100644
--- a/vendor/github.com/fatih/color/doc.go
+++ b/vendor/github.com/fatih/color/doc.go
@@ -37,6 +37,11 @@ separate color object.
whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with White background.")
+ // Use your own io.Writer output
+ color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
+
+ blue := color.New(color.FgBlue)
+ blue.Fprint(myWriter, "This will print text in blue.")
You can create PrintXxx functions to simplify even more:
@@ -49,6 +54,15 @@ You can create PrintXxx functions to simplify even more:
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("don't forget this...")
+You can also FprintXxx functions to pass your own io.Writer:
+
+ blue := color.New(FgBlue).FprintfFunc()
+ blue(myWriter, "important notice: %s", stars)
+
+ // Mix up with multiple attributes
+ success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
+ success(myWriter, don't forget this...")
+
Or create SprintXxx functions to mix strings with other non-colorized strings:
diff --git a/vendor/github.com/gizak/termui/barchart.go b/vendor/github.com/gizak/termui/barchart.go
index 9e2a10689..1102f3416 100644
--- a/vendor/github.com/gizak/termui/barchart.go
+++ b/vendor/github.com/gizak/termui/barchart.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/block.go b/vendor/github.com/gizak/termui/block.go
index 418738c8d..43a4c4039 100644
--- a/vendor/github.com/gizak/termui/block.go
+++ b/vendor/github.com/gizak/termui/block.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/block_common.go b/vendor/github.com/gizak/termui/block_common.go
index 0f972cbbd..aa4a92a7d 100644
--- a/vendor/github.com/gizak/termui/block_common.go
+++ b/vendor/github.com/gizak/termui/block_common.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/block_windows.go b/vendor/github.com/gizak/termui/block_windows.go
index 4dbc017de..50480e55b 100644
--- a/vendor/github.com/gizak/termui/block_windows.go
+++ b/vendor/github.com/gizak/termui/block_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/buffer.go b/vendor/github.com/gizak/termui/buffer.go
index 60e77863a..cbbab6f50 100644
--- a/vendor/github.com/gizak/termui/buffer.go
+++ b/vendor/github.com/gizak/termui/buffer.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -46,7 +46,7 @@ func (b Buffer) Bounds() image.Rectangle {
y0 = p.Y
}
}
- return image.Rect(x0, y0, x1, y1)
+ return image.Rect(x0, y0, x1+1, y1+1)
}
// SetArea assigns a new rect area to Buffer b.
@@ -56,7 +56,7 @@ func (b *Buffer) SetArea(r image.Rectangle) {
}
// Sync sets drawing area to the buffer's bound
-func (b Buffer) Sync() {
+func (b *Buffer) Sync() {
b.SetArea(b.Bounds())
}
diff --git a/vendor/github.com/gizak/termui/canvas.go b/vendor/github.com/gizak/termui/canvas.go
index 4173780f3..911a6787f 100644
--- a/vendor/github.com/gizak/termui/canvas.go
+++ b/vendor/github.com/gizak/termui/canvas.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/config b/vendor/github.com/gizak/termui/config
deleted file mode 100755
index 18fd6a401..000000000
--- a/vendor/github.com/gizak/termui/config
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env perl6
-
-use v6;
-
-my $copyright = '// 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.
-
-';
-
-sub MAIN('update-docstr', Str $srcp) {
- if $srcp.IO.f {
- $_ = $srcp.IO.slurp;
- if m/^ \/\/\s Copyright .+? \n\n/ {
- unless ~$/ eq $copyright {
- s/^ \/\/\s Copyright .+? \n\n /$copyright/;
- spurt $srcp, $_;
- say "[updated] doc string for:"~$srcp;
- }
- } else {
- say "[added] doc string for "~$srcp~" (no match found)";
- $_ = $copyright ~ $_;
- spurt $srcp, $_;
- }
- }
-}
diff --git a/vendor/github.com/gizak/termui/config.py b/vendor/github.com/gizak/termui/config.py
new file mode 100644
index 000000000..9152bf517
--- /dev/null
+++ b/vendor/github.com/gizak/termui/config.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python3
+
+# use v6;
+#
+# my $copyright = '// 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.
+#
+# ';
+#
+# sub MAIN('update-docstr', Str $srcp) {
+# if $srcp.IO.f {
+# $_ = $srcp.IO.slurp;
+# if m/^ \/\/\s Copyright .+? \n\n/ {
+# unless ~$/ eq $copyright {
+# s/^ \/\/\s Copyright .+? \n\n /$copyright/;
+# spurt $srcp, $_;
+# say "[updated] doc string for:"~$srcp;
+# }
+# } else {
+# say "[added] doc string for "~$srcp~" (no match found)";
+# $_ = $copyright ~ $_;
+# spurt $srcp, $_;
+# }
+# }
+# }
+
+import re
+import os
+import io
+
+copyright = """// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
+// Use of this source code is governed by a MIT license that can
+// be found in the LICENSE file.
+
+"""
+
+exclude_dirs = [".git", "_docs"]
+exclude_files = []
+include_dirs = [".", "debug", "extra", "test", "_example"]
+
+
+def is_target(fpath):
+ if os.path.splitext(fpath)[-1] == ".go":
+ return True
+ return False
+
+
+def update_copyright(fpath):
+ print("processing " + fpath)
+ f = io.open(fpath, 'r', encoding='utf-8')
+ fstr = f.read()
+ f.close()
+
+ # remove old
+ m = re.search('^// Copyright .+?\r?\n\r?\n', fstr, re.MULTILINE|re.DOTALL)
+ if m:
+ fstr = fstr[m.end():]
+
+ # add new
+ fstr = copyright + fstr
+ f = io.open(fpath, 'w',encoding='utf-8')
+ f.write(fstr)
+ f.close()
+
+
+def main():
+ for d in include_dirs:
+ files = [
+ os.path.join(d, f) for f in os.listdir(d)
+ if os.path.isfile(os.path.join(d, f))
+ ]
+ for f in files:
+ if is_target(f):
+ update_copyright(f)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/vendor/github.com/gizak/termui/doc.go b/vendor/github.com/gizak/termui/doc.go
index 0d7108d30..fdf7dd079 100644
--- a/vendor/github.com/gizak/termui/doc.go
+++ b/vendor/github.com/gizak/termui/doc.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/events.go b/vendor/github.com/gizak/termui/events.go
index 6627f8942..5ba5263c0 100644
--- a/vendor/github.com/gizak/termui/events.go
+++ b/vendor/github.com/gizak/termui/events.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/gauge.go b/vendor/github.com/gizak/termui/gauge.go
index 01af0ea7c..a143111ea 100644
--- a/vendor/github.com/gizak/termui/gauge.go
+++ b/vendor/github.com/gizak/termui/gauge.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/glide.lock b/vendor/github.com/gizak/termui/glide.lock
index 798e944d3..be5952d46 100644
--- a/vendor/github.com/gizak/termui/glide.lock
+++ b/vendor/github.com/gizak/termui/glide.lock
@@ -1,14 +1,30 @@
-hash: 67a478802ee1d122cf1df063c52458d074864900c96a5cc25dc6be4b7638eb1c
-updated: 2016-04-06T21:16:00.849048757-04:00
+hash: 7a754ba100256404a978b2fc8738aee337beb822458e4b6060399fb89ebd215c
+updated: 2016-11-03T17:39:24.323773674-04:00
imports:
+- name: github.com/maruel/panicparse
+ version: ad661195ed0e88491e0f14be6613304e3b1141d6
+ subpackages:
+ - stack
- name: github.com/mattn/go-runewidth
- version: d6bea18f789704b5f83375793155289da36a3c7f
+ version: 737072b4e32b7a5018b4a7125da8d12de90e8045
- name: github.com/mitchellh/go-wordwrap
version: ad45545899c7b13c020ea92b2072220eefad42b8
- name: github.com/nsf/termbox-go
- version: 362329b0aa6447eadd52edd8d660ec1dff470295
+ version: b6acae516ace002cb8105a89024544a1480655a5
- name: golang.org/x/net
- version: af4fee9d05b66edc24197d189e6118f8ebce8c2b
+ version: 569280fa63be4e201b975e5411e30a92178f0118
subpackages:
- websocket
-devImports: []
+testImports:
+- name: github.com/davecgh/go-spew
+ version: 346938d642f2ec3594ed81d874461961cd0faa76
+ subpackages:
+ - spew
+- name: github.com/pmezard/go-difflib
+ version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
+ subpackages:
+ - difflib
+- name: github.com/stretchr/testify
+ version: 976c720a22c8eb4eb6a0b4348ad85ad12491a506
+ subpackages:
+ - assert
diff --git a/vendor/github.com/gizak/termui/glide.yaml b/vendor/github.com/gizak/termui/glide.yaml
index d8e445254..a6812317f 100644
--- a/vendor/github.com/gizak/termui/glide.yaml
+++ b/vendor/github.com/gizak/termui/glide.yaml
@@ -6,3 +6,4 @@ import:
- package: golang.org/x/net
subpackages:
- websocket
+- package: github.com/maruel/panicparse
diff --git a/vendor/github.com/gizak/termui/grid.go b/vendor/github.com/gizak/termui/grid.go
index 364442e02..679b825b7 100644
--- a/vendor/github.com/gizak/termui/grid.go
+++ b/vendor/github.com/gizak/termui/grid.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/helper.go b/vendor/github.com/gizak/termui/helper.go
index 308f6c1db..5870bac94 100644
--- a/vendor/github.com/gizak/termui/helper.go
+++ b/vendor/github.com/gizak/termui/helper.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/linechart.go b/vendor/github.com/gizak/termui/linechart.go
index 81834efdb..188611496 100644
--- a/vendor/github.com/gizak/termui/linechart.go
+++ b/vendor/github.com/gizak/termui/linechart.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/linechart_others.go b/vendor/github.com/gizak/termui/linechart_others.go
index 7e2e66b3e..fad7a80b1 100644
--- a/vendor/github.com/gizak/termui/linechart_others.go
+++ b/vendor/github.com/gizak/termui/linechart_others.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/linechart_windows.go b/vendor/github.com/gizak/termui/linechart_windows.go
index 1478b5ce3..9c9917ba8 100644
--- a/vendor/github.com/gizak/termui/linechart_windows.go
+++ b/vendor/github.com/gizak/termui/linechart_windows.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/list.go b/vendor/github.com/gizak/termui/list.go
index 0029d2622..492b62d54 100644
--- a/vendor/github.com/gizak/termui/list.go
+++ b/vendor/github.com/gizak/termui/list.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/mbarchart.go b/vendor/github.com/gizak/termui/mbarchart.go
index 6828e6533..fa6d54ca1 100644
--- a/vendor/github.com/gizak/termui/mbarchart.go
+++ b/vendor/github.com/gizak/termui/mbarchart.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/par.go b/vendor/github.com/gizak/termui/par.go
index 78bffd091..14d6b4d34 100644
--- a/vendor/github.com/gizak/termui/par.go
+++ b/vendor/github.com/gizak/termui/par.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/pos.go b/vendor/github.com/gizak/termui/pos.go
index 2046dce5a..a0359af7c 100644
--- a/vendor/github.com/gizak/termui/pos.go
+++ b/vendor/github.com/gizak/termui/pos.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/render.go b/vendor/github.com/gizak/termui/render.go
index 36544f063..be3bf464e 100644
--- a/vendor/github.com/gizak/termui/render.go
+++ b/vendor/github.com/gizak/termui/render.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
@@ -6,9 +6,19 @@ package termui
import (
"image"
+ "io"
"sync"
"time"
+ "fmt"
+
+ "os"
+
+ "runtime/debug"
+
+ "bytes"
+
+ "github.com/maruel/panicparse/stack"
tm "github.com/nsf/termbox-go"
)
@@ -89,7 +99,26 @@ func TermHeight() int {
// Render renders all Bufferer in the given order from left to right,
// right could overlap on left ones.
func render(bs ...Bufferer) {
-
+ defer func() {
+ if e := recover(); e != nil {
+ Close()
+ fmt.Fprintf(os.Stderr, "Captured a panic(value=%v) when rendering Bufferer. Exit termui and clean terminal...\nPrint stack trace:\n\n", e)
+ //debug.PrintStack()
+ gs, err := stack.ParseDump(bytes.NewReader(debug.Stack()), os.Stderr)
+ if err != nil {
+ debug.PrintStack()
+ os.Exit(1)
+ }
+ p := &stack.Palette{}
+ buckets := stack.SortBuckets(stack.Bucketize(gs, stack.AnyValue))
+ srcLen, pkgLen := stack.CalcLengths(buckets, false)
+ for _, bucket := range buckets {
+ io.WriteString(os.Stdout, p.BucketHeader(&bucket, false, len(buckets) > 1))
+ io.WriteString(os.Stdout, p.StackLines(&bucket.Signature, srcLen, pkgLen, false))
+ }
+ os.Exit(1)
+ }
+ }()
for _, b := range bs {
buf := b.Buffer()
diff --git a/vendor/github.com/gizak/termui/sparkline.go b/vendor/github.com/gizak/termui/sparkline.go
index 312ad9563..e127b52e1 100644
--- a/vendor/github.com/gizak/termui/sparkline.go
+++ b/vendor/github.com/gizak/termui/sparkline.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/table.go b/vendor/github.com/gizak/termui/table.go
new file mode 100644
index 000000000..319b89701
--- /dev/null
+++ b/vendor/github.com/gizak/termui/table.go
@@ -0,0 +1,170 @@
+package termui
+
+import "strings"
+
+/*
+ table := termui.NewTable()
+ table.Rows = rows
+ table.FgColor = termui.ColorWhite
+ table.BgColor = termui.ColorDefault
+ table.Height = 7
+ table.Width = 62
+ table.Y = 0
+ table.X = 0
+ table.Border = true
+*/
+
+type Table struct {
+ Block
+ Rows [][]string
+ CellWidth []int
+ FgColor Attribute
+ BgColor Attribute
+ FgColors []Attribute
+ BgColors []Attribute
+ Seperator bool
+ TextAlign Align
+}
+
+func NewTable() *Table {
+ table := &Table{Block: *NewBlock()}
+ table.FgColor = ColorWhite
+ table.BgColor = ColorDefault
+ table.Seperator = true
+ return table
+}
+
+func (table *Table) Analysis() {
+ length := len(table.Rows)
+ if length < 1 {
+ return
+ }
+
+ if len(table.FgColors) == 0 {
+ table.FgColors = make([]Attribute, len(table.Rows))
+ }
+ if len(table.BgColors) == 0 {
+ table.BgColors = make([]Attribute, len(table.Rows))
+ }
+
+ row_width := len(table.Rows[0])
+ cellWidthes := make([]int, row_width)
+
+ for index, row := range table.Rows {
+ for i, str := range row {
+ if cellWidthes[i] < len(str) {
+ cellWidthes[i] = len(str)
+ }
+ }
+
+ if table.FgColors[index] == 0 {
+ table.FgColors[index] = table.FgColor
+ }
+
+ if table.BgColors[index] == 0 {
+ table.BgColors[index] = table.BgColor
+ }
+ }
+
+ table.CellWidth = cellWidthes
+
+ //width_sum := 2
+ //for i, width := range cellWidthes {
+ // width_sum += (width + 2)
+ // for u, row := range table.Rows {
+ // switch table.TextAlign {
+ // case "right":
+ // row[i] = fmt.Sprintf(" %*s ", width, table.Rows[u][i])
+ // case "center":
+ // word_width := len(table.Rows[u][i])
+ // offset := (width - word_width) / 2
+ // row[i] = fmt.Sprintf(" %*s ", width, fmt.Sprintf("%-*s", offset+word_width, table.Rows[u][i]))
+ // default: // left
+ // row[i] = fmt.Sprintf(" %-*s ", width, table.Rows[u][i])
+ // }
+ // }
+ //}
+
+ //if table.Width == 0 {
+ // table.Width = width_sum
+ //}
+}
+
+func (table *Table) SetSize() {
+ length := len(table.Rows)
+ if table.Seperator {
+ table.Height = length*2 + 1
+ } else {
+ table.Height = length + 2
+ }
+ table.Width = 2
+ if length != 0 {
+ for _, cell_width := range table.CellWidth {
+ table.Width += cell_width + 3
+ }
+ }
+}
+
+func (table *Table) CalculatePosition(x int, y int, x_coordinate *int, y_coordibate *int, cell_beginning *int) {
+ if table.Seperator {
+ *y_coordibate = table.innerArea.Min.Y + y*2
+ } else {
+ *y_coordibate = table.innerArea.Min.Y + y
+ }
+ if x == 0 {
+ *cell_beginning = table.innerArea.Min.X
+ } else {
+ *cell_beginning += table.CellWidth[x-1] + 3
+ }
+
+ switch table.TextAlign {
+ case AlignRight:
+ *x_coordinate = *cell_beginning + (table.CellWidth[x] - len(table.Rows[y][x])) + 2
+ case AlignCenter:
+ *x_coordinate = *cell_beginning + (table.CellWidth[x]-len(table.Rows[y][x]))/2 + 2
+ default:
+ *x_coordinate = *cell_beginning + 2
+ }
+}
+
+func (table *Table) Buffer() Buffer {
+ buffer := table.Block.Buffer()
+ table.Analysis()
+
+ pointer_x := table.innerArea.Min.X + 2
+ pointer_y := table.innerArea.Min.Y
+ border_pointer_x := table.innerArea.Min.X
+ for y, row := range table.Rows {
+ for x, cell := range row {
+ table.CalculatePosition(x, y, &pointer_x, &pointer_y, &border_pointer_x)
+ backgraound := DefaultTxBuilder.Build(strings.Repeat(" ", table.CellWidth[x]+3), table.BgColors[y], table.BgColors[y])
+ cells := DefaultTxBuilder.Build(cell, table.FgColors[y], table.BgColors[y])
+
+ for i, back := range backgraound {
+ buffer.Set(border_pointer_x+i, pointer_y, back)
+ }
+
+ coordinate_x := pointer_x
+ for _, printer := range cells {
+ buffer.Set(coordinate_x, pointer_y, printer)
+ coordinate_x += printer.Width()
+ }
+
+ if x != 0 {
+ devidors := DefaultTxBuilder.Build("|", table.FgColors[y], table.BgColors[y])
+ for _, devidor := range devidors {
+ buffer.Set(border_pointer_x, pointer_y, devidor)
+ }
+ }
+ }
+
+ if table.Seperator {
+ border := DefaultTxBuilder.Build(strings.Repeat("─", table.Width-2), table.FgColor, table.BgColor)
+ for i, cell := range border {
+ buffer.Set(i+1, pointer_y+1, cell)
+ }
+ }
+ }
+
+ return buffer
+}
diff --git a/vendor/github.com/gizak/termui/textbuilder.go b/vendor/github.com/gizak/termui/textbuilder.go
index 06a019bed..818a40022 100644
--- a/vendor/github.com/gizak/termui/textbuilder.go
+++ b/vendor/github.com/gizak/termui/textbuilder.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/theme.go b/vendor/github.com/gizak/termui/theme.go
index c3ccda559..9632ae791 100644
--- a/vendor/github.com/gizak/termui/theme.go
+++ b/vendor/github.com/gizak/termui/theme.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/gizak/termui/widget.go b/vendor/github.com/gizak/termui/widget.go
index 35cf143a3..f14aa8602 100644
--- a/vendor/github.com/gizak/termui/widget.go
+++ b/vendor/github.com/gizak/termui/widget.go
@@ -1,4 +1,4 @@
-// Copyright 2016 Zack Guo <gizak@icloud.com>. All rights reserved.
+// Copyright 2016 Zack Guo <zack.y.guo@gmail.com>. All rights reserved.
// Use of this source code is governed by a MIT license that can
// be found in the LICENSE file.
diff --git a/vendor/github.com/huin/goupnp/README.md b/vendor/github.com/huin/goupnp/README.md
index a228ccea6..433ba5c68 100644
--- a/vendor/github.com/huin/goupnp/README.md
+++ b/vendor/github.com/huin/goupnp/README.md
@@ -8,18 +8,18 @@ Run `go get -u github.com/huin/goupnp`.
Documentation
-------------
-All doc links below are for ![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg).
-
Supported DCPs (you probably want to start with one of these):
-* [av1](https://godoc.org/github.com/huin/goupnp/dcps/av1) - Client for UPnP Device Control Protocol MediaServer v1 and MediaRenderer v1.
-* [internetgateway1](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway1) - Client for UPnP Device Control Protocol Internet Gateway Device v1.
-* [internetgateway2](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway2) - Client for UPnP Device Control Protocol Internet Gateway Device v2.
+
+* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) av1](https://godoc.org/github.com/huin/goupnp/dcps/av1) - Client for UPnP Device Control Protocol MediaServer v1 and MediaRenderer v1.
+* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) internetgateway1](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway1) - Client for UPnP Device Control Protocol Internet Gateway Device v1.
+* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) internetgateway2](https://godoc.org/github.com/huin/goupnp/dcps/internetgateway2) - Client for UPnP Device Control Protocol Internet Gateway Device v2.
Core components:
-* [(goupnp)](https://godoc.org/github.com/huin/goupnp) core library - contains datastructures and utilities typically used by the implemented DCPs.
-* [httpu](https://godoc.org/github.com/huin/goupnp/httpu) HTTPU implementation, underlies SSDP.
-* [ssdp](https://godoc.org/github.com/huin/goupnp/ssdp) SSDP client implementation (simple service discovery protocol) - used to discover UPnP services on a network.
-* [soap](https://godoc.org/github.com/huin/goupnp/soap) SOAP client implementation (simple object access protocol) - used to communicate with discovered services.
+
+* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) (goupnp)](https://godoc.org/github.com/huin/goupnp) core library - contains datastructures and utilities typically used by the implemented DCPs.
+* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) httpu](https://godoc.org/github.com/huin/goupnp/httpu) HTTPU implementation, underlies SSDP.
+* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) ssdp](https://godoc.org/github.com/huin/goupnp/ssdp) SSDP client implementation (simple service discovery protocol) - used to discover UPnP services on a network.
+* [![GoDoc](https://godoc.org/github.com/huin/goupnp?status.svg) soap](https://godoc.org/github.com/huin/goupnp/soap) SOAP client implementation (simple object access protocol) - used to communicate with discovered services.
Regenerating dcps generated source code:
diff --git a/vendor/github.com/maruel/panicparse/.travis.yml b/vendor/github.com/maruel/panicparse/.travis.yml
new file mode 100644
index 000000000..c6da8f0b8
--- /dev/null
+++ b/vendor/github.com/maruel/panicparse/.travis.yml
@@ -0,0 +1,15 @@
+# Copyright 2014 Marc-Antoine Ruel. All rights reserved.
+# Use of this source code is governed under the Apache License, Version 2.0
+# that can be found in the LICENSE file.
+
+sudo: false
+language: go
+
+go:
+- tip
+
+before_install:
+ - go get github.com/maruel/pre-commit-go/cmd/pcg
+
+script:
+ - pcg
diff --git a/vendor/github.com/maruel/panicparse/LICENSE b/vendor/github.com/maruel/panicparse/LICENSE
new file mode 100644
index 000000000..b76840c25
--- /dev/null
+++ b/vendor/github.com/maruel/panicparse/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2015 Marc-Antoine Ruel
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/maruel/panicparse/README.md b/vendor/github.com/maruel/panicparse/README.md
new file mode 100644
index 000000000..9fc039cd9
--- /dev/null
+++ b/vendor/github.com/maruel/panicparse/README.md
@@ -0,0 +1,123 @@
+panicparse
+==========
+
+Parses panic stack traces, densifies and deduplicates goroutines with similar
+stack traces. Helps debugging crashes and deadlocks in heavily parallelized
+process.
+
+[![Build Status](https://travis-ci.org/maruel/panicparse.svg?branch=master)](https://travis-ci.org/maruel/panicparse)
+
+panicparse helps make sense of Go crash dumps:
+
+![Screencast](https://raw.githubusercontent.com/wiki/maruel/panicparse/parse.gif "Screencast")
+
+
+Features
+--------
+
+ * >50% more compact output than original stack dump yet more readable.
+ * Exported symbols are bold, private symbols are darker.
+ * Stdlib is green, main is yellow, rest is red.
+ * Deduplicates redundant goroutine stacks. Useful for large server crashes.
+ * Arguments as pointer IDs instead of raw pointer values.
+ * Pushes stdlib-only stacks at the bottom to help focus on important code.
+ * Usable as a library!
+ [![GoDoc](https://godoc.org/github.com/maruel/panicparse/stack?status.svg)](https://godoc.org/github.com/maruel/panicparse/stack)
+ * Warning: please pin the version (e.g. vendor it). Breaking changes are
+ not planned but may happen.
+ * Parses the source files if available to augment the output.
+ * Works on Windows.
+
+
+Installation
+------------
+
+ go get github.com/maruel/panicparse/cmd/pp
+
+
+Usage
+-----
+
+### Piping a stack trace from another process
+
+#### TL;DR
+
+ * Ubuntu (bash v4 or zsh): `|&`
+ * OSX, [install bash 4+](README.md#updating-bash-on-osx), then: `|&`
+ * Windows _or_ OSX with stock bash v3: `2>&1 |`
+ * [Fish](http://fishshell.com/) shell: `^|`
+
+
+#### Longer version
+
+`pp` streams its stdin to stdout as long as it doesn't detect any panic.
+`panic()` and Go's native deadlock detector [print to
+stderr](https://golang.org/src/runtime/panic1.go) via the native [`print()`
+function](https://golang.org/pkg/builtin/#print).
+
+
+**Bash v4** or **zsh**: `|&` tells the shell to redirect stderr to stdout,
+it's an alias for `2>&1 |` ([bash
+v4](https://www.gnu.org/software/bash/manual/bash.html#Pipelines),
+[zsh](http://zsh.sourceforge.net/Doc/Release/Shell-Grammar.html#Simple-Commands-_0026-Pipelines)):
+
+ go test -v |&pp
+
+
+**Windows or OSX native bash** [(which is
+3.2.57)](http://meta.ath0.com/2012/02/05/apples-great-gpl-purge/): They don't
+have this shortcut, so use the long form:
+
+ go test -v 2>&1 | pp
+
+
+**Fish**: It uses [^ for stderr
+redirection](http://fishshell.com/docs/current/tutorial.html#tut_pipes_and_redirections)
+so the shortcut is `^|`:
+
+ go test -v ^|pp
+
+
+**PowerShell**: [It has broken `2>&1` redirection](https://connect.microsoft.com/PowerShell/feedback/details/765551/in-powershell-v3-you-cant-redirect-stderr-to-stdout-without-generating-error-records). The workaround is to shell out to cmd.exe. :(
+
+
+### Investigate deadlock
+
+On POSIX, use `Ctrl-\` to send SIGQUIT to your process, `pp` will ignore
+the signal and will parse the stack trace.
+
+
+### Parsing from a file
+
+To dump to a file then parse, pass the file path of a stack trace
+
+ go test 2> stack.txt
+ pp stack.txt
+
+
+Tips
+----
+
+### GOTRACEBACK
+
+Starting with Go 1.6, [`GOTRACEBACK`](https://golang.org/pkg/runtime/) defaults
+to `single` instead of `all` / `1` that was used in 1.5 and before. To get all
+goroutines trace and not just the crashing one, set the environment variable:
+
+ export GOTRACEBACK=all
+
+or `set GOTRACEBACK=all` on Windows. Probably worth to put it in your `.bashrc`.
+
+
+### Updating bash on OSX
+
+Install bash v4+ on OSX via [homebrew](http://brew.sh) or
+[macports](https://www.macports.org/). Your future self will appreciate having
+done that.
+
+
+### If you have `/usr/bin/pp` installed
+
+You may have the Perl PAR Packager installed. Use long name `panicparse` then;
+
+ go get github.com/maruel/panicparse
diff --git a/vendor/github.com/maruel/panicparse/stack/source.go b/vendor/github.com/maruel/panicparse/stack/source.go
new file mode 100644
index 000000000..f09e67336
--- /dev/null
+++ b/vendor/github.com/maruel/panicparse/stack/source.go
@@ -0,0 +1,291 @@
+// Copyright 2015 Marc-Antoine Ruel. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+// This file contains the code to process sources, to be able to deduct the
+// original types.
+
+package stack
+
+import (
+ "bytes"
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "io/ioutil"
+ "log"
+ "math"
+ "strings"
+)
+
+// cache is a cache of sources on the file system.
+type cache struct {
+ files map[string][]byte
+ parsed map[string]*parsedFile
+}
+
+// Augment processes source files to improve calls to be more descriptive.
+//
+// It modifies goroutines in place.
+func Augment(goroutines []Goroutine) {
+ c := &cache{}
+ for i := range goroutines {
+ c.augmentGoroutine(&goroutines[i])
+ }
+}
+
+// augmentGoroutine processes source files to improve call to be more
+// descriptive.
+//
+// It modifies the routine.
+func (c *cache) augmentGoroutine(goroutine *Goroutine) {
+ if c.files == nil {
+ c.files = map[string][]byte{}
+ }
+ if c.parsed == nil {
+ c.parsed = map[string]*parsedFile{}
+ }
+ // For each call site, look at the next call and populate it. Then we can
+ // walk back and reformat things.
+ for i := range goroutine.Stack.Calls {
+ c.load(goroutine.Stack.Calls[i].SourcePath)
+ }
+
+ // Once all loaded, we can look at the next call when available.
+ for i := 1; i < len(goroutine.Stack.Calls); i++ {
+ // Get the AST from the previous call and process the call line with it.
+ if f := c.getFuncAST(&goroutine.Stack.Calls[i]); f != nil {
+ processCall(&goroutine.Stack.Calls[i], f)
+ }
+ }
+}
+
+// Private stuff.
+
+// load loads a source file and parses the AST tree. Failures are ignored.
+func (c *cache) load(fileName string) {
+ if _, ok := c.parsed[fileName]; ok {
+ return
+ }
+ c.parsed[fileName] = nil
+ if !strings.HasSuffix(fileName, ".go") {
+ // Ignore C and assembly.
+ c.files[fileName] = nil
+ return
+ }
+ log.Printf("load(%s)", fileName)
+ if _, ok := c.files[fileName]; !ok {
+ var err error
+ if c.files[fileName], err = ioutil.ReadFile(fileName); err != nil {
+ log.Printf("Failed to read %s: %s", fileName, err)
+ c.files[fileName] = nil
+ return
+ }
+ }
+ fset := token.NewFileSet()
+ src := c.files[fileName]
+ parsed, err := parser.ParseFile(fset, fileName, src, 0)
+ if err != nil {
+ log.Printf("Failed to parse %s: %s", fileName, err)
+ return
+ }
+ // Convert the line number into raw file offset.
+ offsets := []int{0, 0}
+ start := 0
+ for l := 1; start < len(src); l++ {
+ start += bytes.IndexByte(src[start:], '\n') + 1
+ offsets = append(offsets, start)
+ }
+ c.parsed[fileName] = &parsedFile{offsets, parsed}
+}
+
+func (c *cache) getFuncAST(call *Call) *ast.FuncDecl {
+ if p := c.parsed[call.SourcePath]; p != nil {
+ return p.getFuncAST(call.Func.Name(), call.Line)
+ }
+ return nil
+}
+
+type parsedFile struct {
+ lineToByteOffset []int
+ parsed *ast.File
+}
+
+// getFuncAST gets the callee site function AST representation for the code
+// inside the function f at line l.
+func (p *parsedFile) getFuncAST(f string, l int) (d *ast.FuncDecl) {
+ // Walk the AST to find the lineToByteOffset that fits the line number.
+ var lastFunc *ast.FuncDecl
+ var found ast.Node
+ // Inspect() goes depth first. This means for example that a function like:
+ // func a() {
+ // b := func() {}
+ // c()
+ // }
+ //
+ // Were we are looking at the c() call can return confused values. It is
+ // important to look at the actual ast.Node hierarchy.
+ ast.Inspect(p.parsed, func(n ast.Node) bool {
+ if d != nil {
+ return false
+ }
+ if n == nil {
+ return true
+ }
+ if found != nil {
+ // We are walking up.
+ }
+ if int(n.Pos()) >= p.lineToByteOffset[l] {
+ // We are expecting a ast.CallExpr node. It can be harder to figure out
+ // when there are multiple calls on a single line, as the stack trace
+ // doesn't have file byte offset information, only line based.
+ // gofmt will always format to one function call per line but there can
+ // be edge cases, like:
+ // a = A{Foo(), Bar()}
+ d = lastFunc
+ //p.processNode(call, n)
+ return false
+ } else if f, ok := n.(*ast.FuncDecl); ok {
+ lastFunc = f
+ }
+ return true
+ })
+ return
+}
+
+func name(n ast.Node) string {
+ if _, ok := n.(*ast.InterfaceType); ok {
+ return "interface{}"
+ }
+ if i, ok := n.(*ast.Ident); ok {
+ return i.Name
+ }
+ if _, ok := n.(*ast.FuncType); ok {
+ return "func"
+ }
+ if s, ok := n.(*ast.SelectorExpr); ok {
+ return s.Sel.Name
+ }
+ // TODO(maruel): Implement anything missing.
+ return "<unknown>"
+}
+
+// fieldToType returns the type name and whether if it's an ellipsis.
+func fieldToType(f *ast.Field) (string, bool) {
+ switch arg := f.Type.(type) {
+ case *ast.ArrayType:
+ return "[]" + name(arg.Elt), false
+ case *ast.Ellipsis:
+ return name(arg.Elt), true
+ case *ast.FuncType:
+ // Do not print the function signature to not overload the trace.
+ return "func", false
+ case *ast.Ident:
+ return arg.Name, false
+ case *ast.InterfaceType:
+ return "interface{}", false
+ case *ast.SelectorExpr:
+ return arg.Sel.Name, false
+ case *ast.StarExpr:
+ return "*" + name(arg.X), false
+ default:
+ // TODO(maruel): Implement anything missing.
+ return "<unknown>", false
+ }
+}
+
+// extractArgumentsType returns the name of the type of each input argument.
+func extractArgumentsType(f *ast.FuncDecl) ([]string, bool) {
+ var fields []*ast.Field
+ if f.Recv != nil {
+ if len(f.Recv.List) != 1 {
+ panic("Expect only one receiver; please fix panicparse's code")
+ }
+ // If it is an object receiver (vs a pointer receiver), its address is not
+ // printed in the stack trace so it needs to be ignored.
+ if _, ok := f.Recv.List[0].Type.(*ast.StarExpr); ok {
+ fields = append(fields, f.Recv.List[0])
+ }
+ }
+ var types []string
+ extra := false
+ for _, arg := range append(fields, f.Type.Params.List...) {
+ // Assert that extra is only set on the last item of fields?
+ var t string
+ t, extra = fieldToType(arg)
+ mult := len(arg.Names)
+ if mult == 0 {
+ mult = 1
+ }
+ for i := 0; i < mult; i++ {
+ types = append(types, t)
+ }
+ }
+ return types, extra
+}
+
+// processCall walks the function and populate call accordingly.
+func processCall(call *Call, f *ast.FuncDecl) {
+ values := make([]uint64, len(call.Args.Values))
+ for i := range call.Args.Values {
+ values[i] = call.Args.Values[i].Value
+ }
+ index := 0
+ pop := func() uint64 {
+ if len(values) != 0 {
+ x := values[0]
+ values = values[1:]
+ index++
+ return x
+ }
+ return 0
+ }
+ popName := func() string {
+ n := call.Args.Values[index].Name
+ v := pop()
+ if len(n) == 0 {
+ return fmt.Sprintf("0x%x", v)
+ }
+ return n
+ }
+
+ types, extra := extractArgumentsType(f)
+ for i := 0; len(values) != 0; i++ {
+ var t string
+ if i >= len(types) {
+ if !extra {
+ // These are unexpected value! Print them as hex.
+ call.Args.Processed = append(call.Args.Processed, popName())
+ continue
+ }
+ t = types[len(types)-1]
+ } else {
+ t = types[i]
+ }
+ switch t {
+ case "float32":
+ call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%g", math.Float32frombits(uint32(pop()))))
+ case "float64":
+ call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%g", math.Float64frombits(pop())))
+ case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64":
+ call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%d", pop()))
+ case "string":
+ call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s, len=%d)", t, popName(), pop()))
+ default:
+ if strings.HasPrefix(t, "*") {
+ call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s)", t, popName()))
+ } else if strings.HasPrefix(t, "[]") {
+ call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s len=%d cap=%d)", t, popName(), pop(), pop()))
+ } else {
+ // Assumes it's an interface. For now, discard the object value, which
+ // is probably not a good idea.
+ call.Args.Processed = append(call.Args.Processed, fmt.Sprintf("%s(%s)", t, popName()))
+ pop()
+ }
+ }
+ if len(values) == 0 && call.Args.Elided {
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/maruel/panicparse/stack/stack.go b/vendor/github.com/maruel/panicparse/stack/stack.go
new file mode 100644
index 000000000..cfb502e66
--- /dev/null
+++ b/vendor/github.com/maruel/panicparse/stack/stack.go
@@ -0,0 +1,832 @@
+// Copyright 2015 Marc-Antoine Ruel. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+// Package stack analyzes stack dump of Go processes and simplifies it.
+//
+// It is mostly useful on servers will large number of identical goroutines,
+// making the crash dump harder to read than strictly necesary.
+package stack
+
+import (
+ "bufio"
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "net/url"
+ "os"
+ "path/filepath"
+ "regexp"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf8"
+)
+
+const lockedToThread = "locked to thread"
+
+var (
+ // TODO(maruel): Handle corrupted stack cases:
+ // - missed stack barrier
+ // - found next stack barrier at 0x123; expected
+ // - runtime: unexpected return pc for FUNC_NAME called from 0x123
+
+ reRoutineHeader = regexp.MustCompile("^goroutine (\\d+) \\[([^\\]]+)\\]\\:\n$")
+ reMinutes = regexp.MustCompile("^(\\d+) minutes$")
+ reUnavail = regexp.MustCompile("^(?:\t| +)goroutine running on other thread; stack unavailable")
+ // See gentraceback() in src/runtime/traceback.go for more information.
+ // - Sometimes the source file comes up as "<autogenerated>". It is the
+ // compiler than generated these, not the runtime.
+ // - The tab may be replaced with spaces when a user copy-paste it, handle
+ // this transparently.
+ // - "runtime.gopanic" is explicitly replaced with "panic" by gentraceback().
+ // - The +0x123 byte offset is printed when frame.pc > _func.entry. _func is
+ // generated by the linker.
+ // - The +0x123 byte offset is not included with generated code, e.g. unnamed
+ // functions "func·006()" which is generally go func() { ... }()
+ // statements. Since the _func is generated at runtime, it's probably why
+ // _func.entry is not set.
+ // - C calls may have fp=0x123 sp=0x123 appended. I think it normally happens
+ // when a signal is not correctly handled. It is printed with m.throwing>0.
+ // These are discarded.
+ // - For cgo, the source file may be "??".
+ reFile = regexp.MustCompile("^(?:\t| +)(\\?\\?|\\<autogenerated\\>|.+\\.(?:c|go|s))\\:(\\d+)(?:| \\+0x[0-9a-f]+)(?:| fp=0x[0-9a-f]+ sp=0x[0-9a-f]+)\n$")
+ // Sadly, it doesn't note the goroutine number so we could cascade them per
+ // parenthood.
+ reCreated = regexp.MustCompile("^created by (.+)\n$")
+ reFunc = regexp.MustCompile("^(.+)\\((.*)\\)\n$")
+ reElided = regexp.MustCompile("^\\.\\.\\.additional frames elided\\.\\.\\.\n$")
+ // Include frequent GOROOT value on Windows, distro provided and user
+ // installed path. This simplifies the user's life when processing a trace
+ // generated on another VM.
+ // TODO(maruel): Guess the path automatically via traces containing the
+ // 'runtime' package, which is very frequent. This would be "less bad" than
+ // throwing up random values at the parser.
+ goroots = []string{runtime.GOROOT(), "c:/go", "/usr/lib/go", "/usr/local/go"}
+)
+
+// Similarity is the level at which two call lines arguments must match to be
+// considered similar enough to coalesce them.
+type Similarity int
+
+const (
+ // ExactFlags requires same bits (e.g. Locked).
+ ExactFlags Similarity = iota
+ // ExactLines requests the exact same arguments on the call line.
+ ExactLines
+ // AnyPointer considers different pointers a similar call line.
+ AnyPointer
+ // AnyValue accepts any value as similar call line.
+ AnyValue
+)
+
+// Function is a function call.
+//
+// Go stack traces print a mangled function call, this wrapper unmangle the
+// string before printing and adds other filtering methods.
+type Function struct {
+ Raw string
+}
+
+// String is the fully qualified function name.
+//
+// Sadly Go is a bit confused when the package name doesn't match the directory
+// containing the source file and will use the directory name instead of the
+// real package name.
+func (f Function) String() string {
+ s, _ := url.QueryUnescape(f.Raw)
+ return s
+}
+
+// Name is the naked function name.
+func (f Function) Name() string {
+ parts := strings.SplitN(filepath.Base(f.Raw), ".", 2)
+ if len(parts) == 1 {
+ return parts[0]
+ }
+ return parts[1]
+}
+
+// PkgName is the package name for this function reference.
+func (f Function) PkgName() string {
+ parts := strings.SplitN(filepath.Base(f.Raw), ".", 2)
+ if len(parts) == 1 {
+ return ""
+ }
+ s, _ := url.QueryUnescape(parts[0])
+ return s
+}
+
+// PkgDotName returns "<package>.<func>" format.
+func (f Function) PkgDotName() string {
+ parts := strings.SplitN(filepath.Base(f.Raw), ".", 2)
+ s, _ := url.QueryUnescape(parts[0])
+ if len(parts) == 1 {
+ return parts[0]
+ }
+ if s != "" || parts[1] != "" {
+ return s + "." + parts[1]
+ }
+ return ""
+}
+
+// IsExported returns true if the function is exported.
+func (f Function) IsExported() bool {
+ name := f.Name()
+ parts := strings.Split(name, ".")
+ r, _ := utf8.DecodeRuneInString(parts[len(parts)-1])
+ if unicode.ToUpper(r) == r {
+ return true
+ }
+ return f.PkgName() == "main" && name == "main"
+}
+
+// Arg is an argument on a Call.
+type Arg struct {
+ Value uint64 // Value is the raw value as found in the stack trace
+ Name string // Name is a pseudo name given to the argument
+}
+
+// IsPtr returns true if we guess it's a pointer. It's only a guess, it can be
+// easily be confused by a bitmask.
+func (a *Arg) IsPtr() bool {
+ // Assumes all pointers are above 16Mb and positive.
+ return a.Value > 16*1024*1024 && a.Value < math.MaxInt64
+}
+
+func (a Arg) String() string {
+ if a.Name != "" {
+ return a.Name
+ }
+ if a.Value == 0 {
+ return "0"
+ }
+ return fmt.Sprintf("0x%x", a.Value)
+}
+
+// Args is a series of function call arguments.
+type Args struct {
+ Values []Arg // Values is the arguments as shown on the stack trace. They are mangled via simplification.
+ Processed []string // Processed is the arguments generated from processing the source files. It can have a length lower than Values.
+ Elided bool // If set, it means there was a trailing ", ..."
+}
+
+func (a Args) String() string {
+ var v []string
+ if len(a.Processed) != 0 {
+ v = make([]string, 0, len(a.Processed))
+ for _, item := range a.Processed {
+ v = append(v, item)
+ }
+ } else {
+ v = make([]string, 0, len(a.Values))
+ for _, item := range a.Values {
+ v = append(v, item.String())
+ }
+ }
+ if a.Elided {
+ v = append(v, "...")
+ }
+ return strings.Join(v, ", ")
+}
+
+// Equal returns true only if both arguments are exactly equal.
+func (a *Args) Equal(r *Args) bool {
+ if a.Elided != r.Elided || len(a.Values) != len(r.Values) {
+ return false
+ }
+ for i, l := range a.Values {
+ if l != r.Values[i] {
+ return false
+ }
+ }
+ return true
+}
+
+// Similar returns true if the two Args are equal or almost but not quite
+// equal.
+func (a *Args) Similar(r *Args, similar Similarity) bool {
+ if a.Elided != r.Elided || len(a.Values) != len(r.Values) {
+ return false
+ }
+ if similar == AnyValue {
+ return true
+ }
+ for i, l := range a.Values {
+ switch similar {
+ case ExactFlags, ExactLines:
+ if l != r.Values[i] {
+ return false
+ }
+ default:
+ if l.IsPtr() != r.Values[i].IsPtr() || (!l.IsPtr() && l != r.Values[i]) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// Merge merges two similar Args, zapping out differences.
+func (a *Args) Merge(r *Args) Args {
+ out := Args{
+ Values: make([]Arg, len(a.Values)),
+ Elided: a.Elided,
+ }
+ for i, l := range a.Values {
+ if l != r.Values[i] {
+ out.Values[i].Name = "*"
+ out.Values[i].Value = l.Value
+ } else {
+ out.Values[i] = l
+ }
+ }
+ return out
+}
+
+// Call is an item in the stack trace.
+type Call struct {
+ SourcePath string // Full path name of the source file
+ Line int // Line number
+ Func Function // Fully qualified function name (encoded).
+ Args Args // Call arguments
+}
+
+// Equal returns true only if both calls are exactly equal.
+func (c *Call) Equal(r *Call) bool {
+ return c.SourcePath == r.SourcePath && c.Line == r.Line && c.Func == r.Func && c.Args.Equal(&r.Args)
+}
+
+// Similar returns true if the two Call are equal or almost but not quite
+// equal.
+func (c *Call) Similar(r *Call, similar Similarity) bool {
+ return c.SourcePath == r.SourcePath && c.Line == r.Line && c.Func == r.Func && c.Args.Similar(&r.Args, similar)
+}
+
+// Merge merges two similar Call, zapping out differences.
+func (c *Call) Merge(r *Call) Call {
+ return Call{
+ SourcePath: c.SourcePath,
+ Line: c.Line,
+ Func: c.Func,
+ Args: c.Args.Merge(&r.Args),
+ }
+}
+
+// SourceName returns the base file name of the source file.
+func (c *Call) SourceName() string {
+ return filepath.Base(c.SourcePath)
+}
+
+// SourceLine returns "source.go:line", including only the base file name.
+func (c *Call) SourceLine() string {
+ return fmt.Sprintf("%s:%d", c.SourceName(), c.Line)
+}
+
+// FullSourceLine returns "/path/to/source.go:line".
+func (c *Call) FullSourceLine() string {
+ return fmt.Sprintf("%s:%d", c.SourcePath, c.Line)
+}
+
+// PkgSource is one directory plus the file name of the source file.
+func (c *Call) PkgSource() string {
+ return filepath.Join(filepath.Base(filepath.Dir(c.SourcePath)), c.SourceName())
+}
+
+const testMainSource = "_test" + string(os.PathSeparator) + "_testmain.go"
+
+// IsStdlib returns true if it is a Go standard library function. This includes
+// the 'go test' generated main executable.
+func (c *Call) IsStdlib() bool {
+ for _, goroot := range goroots {
+ if strings.HasPrefix(c.SourcePath, goroot) {
+ return true
+ }
+ }
+ // Consider _test/_testmain.go as stdlib since it's injected by "go test".
+ return c.PkgSource() == testMainSource
+}
+
+// IsPkgMain returns true if it is in the main package.
+func (c *Call) IsPkgMain() bool {
+ return c.Func.PkgName() == "main"
+}
+
+// Stack is a call stack.
+type Stack struct {
+ Calls []Call // Call stack. First is original function, last is leaf function.
+ Elided bool // Happens when there's >100 items in Stack, currently hardcoded in package runtime.
+}
+
+// Equal returns true on if both call stacks are exactly equal.
+func (s *Stack) Equal(r *Stack) bool {
+ if len(s.Calls) != len(r.Calls) || s.Elided != r.Elided {
+ return false
+ }
+ for i := range s.Calls {
+ if !s.Calls[i].Equal(&r.Calls[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// Similar returns true if the two Stack are equal or almost but not quite
+// equal.
+func (s *Stack) Similar(r *Stack, similar Similarity) bool {
+ if len(s.Calls) != len(r.Calls) || s.Elided != r.Elided {
+ return false
+ }
+ for i := range s.Calls {
+ if !s.Calls[i].Similar(&r.Calls[i], similar) {
+ return false
+ }
+ }
+ return true
+}
+
+// Merge merges two similar Stack, zapping out differences.
+func (s *Stack) Merge(r *Stack) *Stack {
+ // Assumes similar stacks have the same length.
+ out := &Stack{
+ Calls: make([]Call, len(s.Calls)),
+ Elided: s.Elided,
+ }
+ for i := range s.Calls {
+ out.Calls[i] = s.Calls[i].Merge(&r.Calls[i])
+ }
+ return out
+}
+
+// Less compares two Stack, where the ones that are less are more
+// important, so they come up front. A Stack with more private functions is
+// 'less' so it is at the top. Inversely, a Stack with only public
+// functions is 'more' so it is at the bottom.
+func (s *Stack) Less(r *Stack) bool {
+ lStdlib := 0
+ lPrivate := 0
+ for _, c := range s.Calls {
+ if c.IsStdlib() {
+ lStdlib++
+ } else {
+ lPrivate++
+ }
+ }
+ rStdlib := 0
+ rPrivate := 0
+ for _, s := range r.Calls {
+ if s.IsStdlib() {
+ rStdlib++
+ } else {
+ rPrivate++
+ }
+ }
+ if lPrivate > rPrivate {
+ return true
+ }
+ if lPrivate < rPrivate {
+ return false
+ }
+ if lStdlib > rStdlib {
+ return false
+ }
+ if lStdlib < rStdlib {
+ return true
+ }
+
+ // Stack lengths are the same.
+ for x := range s.Calls {
+ if s.Calls[x].Func.Raw < r.Calls[x].Func.Raw {
+ return true
+ }
+ if s.Calls[x].Func.Raw > r.Calls[x].Func.Raw {
+ return true
+ }
+ if s.Calls[x].PkgSource() < r.Calls[x].PkgSource() {
+ return true
+ }
+ if s.Calls[x].PkgSource() > r.Calls[x].PkgSource() {
+ return true
+ }
+ if s.Calls[x].Line < r.Calls[x].Line {
+ return true
+ }
+ if s.Calls[x].Line > r.Calls[x].Line {
+ return true
+ }
+ }
+ return false
+}
+
+// Signature represents the signature of one or multiple goroutines.
+//
+// It is effectively the stack trace plus the goroutine internal bits, like
+// it's state, if it is thread locked, which call site created this goroutine,
+// etc.
+type Signature struct {
+ // Use git grep 'gopark(|unlock)\(' to find them all plus everything listed
+ // in runtime/traceback.go. Valid values includes:
+ // - chan send, chan receive, select
+ // - finalizer wait, mark wait (idle),
+ // - Concurrent GC wait, GC sweep wait, force gc (idle)
+ // - IO wait, panicwait
+ // - semacquire, semarelease
+ // - sleep, timer goroutine (idle)
+ // - trace reader (blocked)
+ // Stuck cases:
+ // - chan send (nil chan), chan receive (nil chan), select (no cases)
+ // Runnable states:
+ // - idle, runnable, running, syscall, waiting, dead, enqueue, copystack,
+ // Scan states:
+ // - scan, scanrunnable, scanrunning, scansyscall, scanwaiting, scandead,
+ // scanenqueue
+ State string
+ CreatedBy Call // Which other goroutine which created this one.
+ SleepMin int // Wait time in minutes, if applicable.
+ SleepMax int // Wait time in minutes, if applicable.
+ Stack Stack
+ Locked bool // Locked to an OS thread.
+}
+
+// Equal returns true only if both signatures are exactly equal.
+func (s *Signature) Equal(r *Signature) bool {
+ if s.State != r.State || !s.CreatedBy.Equal(&r.CreatedBy) || s.Locked != r.Locked || s.SleepMin != r.SleepMin || s.SleepMax != r.SleepMax {
+ return false
+ }
+ return s.Stack.Equal(&r.Stack)
+}
+
+// Similar returns true if the two Signature are equal or almost but not quite
+// equal.
+func (s *Signature) Similar(r *Signature, similar Similarity) bool {
+ if s.State != r.State || !s.CreatedBy.Similar(&r.CreatedBy, similar) {
+ return false
+ }
+ if similar == ExactFlags && s.Locked != r.Locked {
+ return false
+ }
+ return s.Stack.Similar(&r.Stack, similar)
+}
+
+// Merge merges two similar Signature, zapping out differences.
+func (s *Signature) Merge(r *Signature) *Signature {
+ min := s.SleepMin
+ if r.SleepMin < min {
+ min = r.SleepMin
+ }
+ max := s.SleepMax
+ if r.SleepMax > max {
+ max = r.SleepMax
+ }
+ return &Signature{
+ State: s.State, // Drop right side.
+ CreatedBy: s.CreatedBy, // Drop right side.
+ SleepMin: min,
+ SleepMax: max,
+ Stack: *s.Stack.Merge(&r.Stack),
+ Locked: s.Locked || r.Locked, // TODO(maruel): This is weirdo.
+ }
+}
+
+// Less compares two Signature, where the ones that are less are more
+// important, so they come up front. A Signature with more private functions is
+// 'less' so it is at the top. Inversely, a Signature with only public
+// functions is 'more' so it is at the bottom.
+func (s *Signature) Less(r *Signature) bool {
+ if s.Stack.Less(&r.Stack) {
+ return true
+ }
+ if r.Stack.Less(&s.Stack) {
+ return false
+ }
+ if s.Locked && !r.Locked {
+ return true
+ }
+ if r.Locked && !s.Locked {
+ return false
+ }
+ if s.State < r.State {
+ return true
+ }
+ if s.State > r.State {
+ return false
+ }
+ return false
+}
+
+// Goroutine represents the state of one goroutine, including the stack trace.
+type Goroutine struct {
+ Signature // It's stack trace, internal bits, state, which call site created it, etc.
+ ID int // Goroutine ID.
+ First bool // First is the goroutine first printed, normally the one that crashed.
+}
+
+// Bucketize returns the number of similar goroutines.
+func Bucketize(goroutines []Goroutine, similar Similarity) map[*Signature][]Goroutine {
+ out := map[*Signature][]Goroutine{}
+ // O(n²). Fix eventually.
+ for _, routine := range goroutines {
+ found := false
+ for key := range out {
+ // When a match is found, this effectively drops the other goroutine ID.
+ if key.Similar(&routine.Signature, similar) {
+ found = true
+ if !key.Equal(&routine.Signature) {
+ // Almost but not quite equal. There's different pointers passed
+ // around but the same values. Zap out the different values.
+ newKey := key.Merge(&routine.Signature)
+ out[newKey] = append(out[key], routine)
+ delete(out, key)
+ } else {
+ out[key] = append(out[key], routine)
+ }
+ break
+ }
+ }
+ if !found {
+ key := &Signature{}
+ *key = routine.Signature
+ out[key] = []Goroutine{routine}
+ }
+ }
+ return out
+}
+
+// Bucket is a stack trace signature and the list of goroutines that fits this
+// signature.
+type Bucket struct {
+ Signature
+ Routines []Goroutine
+}
+
+// First returns true if it contains the first goroutine, e.g. the ones that
+// likely generated the panic() call, if any.
+func (b *Bucket) First() bool {
+ for _, r := range b.Routines {
+ if r.First {
+ return true
+ }
+ }
+ return false
+}
+
+// Less does reverse sort.
+func (b *Bucket) Less(r *Bucket) bool {
+ if b.First() {
+ return true
+ }
+ if r.First() {
+ return false
+ }
+ return b.Signature.Less(&r.Signature)
+}
+
+// Buckets is a list of Bucket sorted by repeation count.
+type Buckets []Bucket
+
+func (b Buckets) Len() int {
+ return len(b)
+}
+
+func (b Buckets) Less(i, j int) bool {
+ return b[i].Less(&b[j])
+}
+
+func (b Buckets) Swap(i, j int) {
+ b[j], b[i] = b[i], b[j]
+}
+
+// SortBuckets creates a list of Bucket from each goroutine stack trace count.
+func SortBuckets(buckets map[*Signature][]Goroutine) Buckets {
+ out := make(Buckets, 0, len(buckets))
+ for signature, count := range buckets {
+ out = append(out, Bucket{*signature, count})
+ }
+ sort.Sort(out)
+ return out
+}
+
+// scanLines is similar to bufio.ScanLines except that it:
+// - doesn't drop '\n'
+// - doesn't strip '\r'
+// - returns when the data is bufio.MaxScanTokenSize bytes
+func scanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
+ if atEOF && len(data) == 0 {
+ return 0, nil, nil
+ }
+ if i := bytes.IndexByte(data, '\n'); i >= 0 {
+ return i + 1, data[0 : i+1], nil
+ }
+ if atEOF {
+ return len(data), data, nil
+ }
+ if len(data) >= bufio.MaxScanTokenSize {
+ // Returns the line even if it is not at EOF nor has a '\n', otherwise the
+ // scanner will return bufio.ErrTooLong which is definitely not what we
+ // want.
+ return len(data), data, nil
+ }
+ return 0, nil, nil
+}
+
+// ParseDump processes the output from runtime.Stack().
+//
+// It supports piping from another command and assumes there is junk before the
+// actual stack trace. The junk is streamed to out.
+func ParseDump(r io.Reader, out io.Writer) ([]Goroutine, error) {
+ goroutines := make([]Goroutine, 0, 16)
+ var goroutine *Goroutine
+ scanner := bufio.NewScanner(r)
+ scanner.Split(scanLines)
+ // TODO(maruel): Use a formal state machine. Patterns follows:
+ // - reRoutineHeader
+ // Either:
+ // - reUnavail
+ // - reFunc + reFile in a loop
+ // - reElided
+ // Optionally ends with:
+ // - reCreated + reFile
+ // Between each goroutine stack dump: an empty line
+ created := false
+ // firstLine is the first line after the reRoutineHeader header line.
+ firstLine := false
+ for scanner.Scan() {
+ line := scanner.Text()
+ if line == "\n" {
+ if goroutine != nil {
+ goroutine = nil
+ continue
+ }
+ } else if line[len(line)-1] == '\n' {
+ if goroutine == nil {
+ if match := reRoutineHeader.FindStringSubmatch(line); match != nil {
+ if id, err := strconv.Atoi(match[1]); err == nil {
+ // See runtime/traceback.go.
+ // "<state>, \d+ minutes, locked to thread"
+ items := strings.Split(match[2], ", ")
+ sleep := 0
+ locked := false
+ for i := 1; i < len(items); i++ {
+ if items[i] == lockedToThread {
+ locked = true
+ continue
+ }
+ // Look for duration, if any.
+ if match2 := reMinutes.FindStringSubmatch(items[i]); match2 != nil {
+ sleep, _ = strconv.Atoi(match2[1])
+ }
+ }
+ goroutines = append(goroutines, Goroutine{
+ Signature: Signature{
+ State: items[0],
+ SleepMin: sleep,
+ SleepMax: sleep,
+ Locked: locked,
+ },
+ ID: id,
+ First: len(goroutines) == 0,
+ })
+ goroutine = &goroutines[len(goroutines)-1]
+ firstLine = true
+ continue
+ }
+ }
+ } else {
+ if firstLine {
+ firstLine = false
+ if match := reUnavail.FindStringSubmatch(line); match != nil {
+ // Generate a fake stack entry.
+ goroutine.Stack.Calls = []Call{{SourcePath: "<unavailable>"}}
+ continue
+ }
+ }
+
+ if match := reFile.FindStringSubmatch(line); match != nil {
+ // Triggers after a reFunc or a reCreated.
+ num, err := strconv.Atoi(match[2])
+ if err != nil {
+ return goroutines, fmt.Errorf("failed to parse int on line: \"%s\"", line)
+ }
+ if created {
+ created = false
+ goroutine.CreatedBy.SourcePath = match[1]
+ goroutine.CreatedBy.Line = num
+ } else {
+ i := len(goroutine.Stack.Calls) - 1
+ if i < 0 {
+ return goroutines, errors.New("unexpected order")
+ }
+ goroutine.Stack.Calls[i].SourcePath = match[1]
+ goroutine.Stack.Calls[i].Line = num
+ }
+ continue
+ }
+
+ if match := reCreated.FindStringSubmatch(line); match != nil {
+ created = true
+ goroutine.CreatedBy.Func.Raw = match[1]
+ continue
+ }
+
+ if match := reFunc.FindStringSubmatch(line); match != nil {
+ args := Args{}
+ for _, a := range strings.Split(match[2], ", ") {
+ if a == "..." {
+ args.Elided = true
+ continue
+ }
+ if a == "" {
+ // Remaining values were dropped.
+ break
+ }
+ v, err := strconv.ParseUint(a, 0, 64)
+ if err != nil {
+ return goroutines, fmt.Errorf("failed to parse int on line: \"%s\"", line)
+ }
+ args.Values = append(args.Values, Arg{Value: v})
+ }
+ goroutine.Stack.Calls = append(goroutine.Stack.Calls, Call{Func: Function{match[1]}, Args: args})
+ continue
+ }
+
+ if match := reElided.FindStringSubmatch(line); match != nil {
+ goroutine.Stack.Elided = true
+ continue
+ }
+ }
+ }
+ _, _ = io.WriteString(out, line)
+ goroutine = nil
+ }
+ nameArguments(goroutines)
+ return goroutines, scanner.Err()
+}
+
+// Private stuff.
+
+func nameArguments(goroutines []Goroutine) {
+ // Set a name for any pointer occuring more than once.
+ type object struct {
+ args []*Arg
+ inPrimary bool
+ id int
+ }
+ objects := map[uint64]object{}
+ // Enumerate all the arguments.
+ for i := range goroutines {
+ for j := range goroutines[i].Stack.Calls {
+ for k := range goroutines[i].Stack.Calls[j].Args.Values {
+ arg := goroutines[i].Stack.Calls[j].Args.Values[k]
+ if arg.IsPtr() {
+ objects[arg.Value] = object{
+ args: append(objects[arg.Value].args, &goroutines[i].Stack.Calls[j].Args.Values[k]),
+ inPrimary: objects[arg.Value].inPrimary || i == 0,
+ }
+ }
+ }
+ }
+ // CreatedBy.Args is never set.
+ }
+ order := uint64Slice{}
+ for k, obj := range objects {
+ if len(obj.args) > 1 && obj.inPrimary {
+ order = append(order, k)
+ }
+ }
+ sort.Sort(order)
+ nextID := 1
+ for _, k := range order {
+ for _, arg := range objects[k].args {
+ arg.Name = fmt.Sprintf("#%d", nextID)
+ }
+ nextID++
+ }
+
+ // Now do the rest. This is done so the output is deterministic.
+ order = uint64Slice{}
+ for k := range objects {
+ order = append(order, k)
+ }
+ sort.Sort(order)
+ for _, k := range order {
+ // Process the remaining pointers, they were not referenced by primary
+ // thread so will have higher IDs.
+ if objects[k].inPrimary {
+ continue
+ }
+ for _, arg := range objects[k].args {
+ arg.Name = fmt.Sprintf("#%d", nextID)
+ }
+ nextID++
+ }
+}
+
+type uint64Slice []uint64
+
+func (a uint64Slice) Len() int { return len(a) }
+func (a uint64Slice) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a uint64Slice) Less(i, j int) bool { return a[i] < a[j] }
diff --git a/vendor/github.com/maruel/panicparse/stack/ui.go b/vendor/github.com/maruel/panicparse/stack/ui.go
new file mode 100644
index 000000000..b125fc940
--- /dev/null
+++ b/vendor/github.com/maruel/panicparse/stack/ui.go
@@ -0,0 +1,139 @@
+// Copyright 2016 Marc-Antoine Ruel. All rights reserved.
+// Use of this source code is governed under the Apache License, Version 2.0
+// that can be found in the LICENSE file.
+
+package stack
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Palette defines the color used.
+//
+// An empty object Palette{} can be used to disable coloring.
+type Palette struct {
+ EOLReset string
+
+ // Routine header.
+ RoutineFirst string // The first routine printed.
+ Routine string // Following routines.
+ CreatedBy string
+
+ // Call line.
+ Package string
+ SourceFile string
+ FunctionStdLib string
+ FunctionStdLibExported string
+ FunctionMain string
+ FunctionOther string
+ FunctionOtherExported string
+ Arguments string
+}
+
+// CalcLengths returns the maximum length of the source lines and package names.
+func CalcLengths(buckets Buckets, fullPath bool) (int, int) {
+ srcLen := 0
+ pkgLen := 0
+ for _, bucket := range buckets {
+ for _, line := range bucket.Signature.Stack.Calls {
+ l := 0
+ if fullPath {
+ l = len(line.FullSourceLine())
+ } else {
+ l = len(line.SourceLine())
+ }
+ if l > srcLen {
+ srcLen = l
+ }
+ l = len(line.Func.PkgName())
+ if l > pkgLen {
+ pkgLen = l
+ }
+ }
+ }
+ return srcLen, pkgLen
+}
+
+// functionColor returns the color to be used for the function name based on
+// the type of package the function is in.
+func (p *Palette) functionColor(line *Call) string {
+ if line.IsStdlib() {
+ if line.Func.IsExported() {
+ return p.FunctionStdLibExported
+ }
+ return p.FunctionStdLib
+ } else if line.IsPkgMain() {
+ return p.FunctionMain
+ } else if line.Func.IsExported() {
+ return p.FunctionOtherExported
+ }
+ return p.FunctionOther
+}
+
+// routineColor returns the color for the header of the goroutines bucket.
+func (p *Palette) routineColor(bucket *Bucket, multipleBuckets bool) string {
+ if bucket.First() && multipleBuckets {
+ return p.RoutineFirst
+ }
+ return p.Routine
+}
+
+// BucketHeader prints the header of a goroutine signature.
+func (p *Palette) BucketHeader(bucket *Bucket, fullPath, multipleBuckets bool) string {
+ extra := ""
+ if bucket.SleepMax != 0 {
+ if bucket.SleepMin != bucket.SleepMax {
+ extra += fmt.Sprintf(" [%d~%d minutes]", bucket.SleepMin, bucket.SleepMax)
+ } else {
+ extra += fmt.Sprintf(" [%d minutes]", bucket.SleepMax)
+ }
+ }
+ if bucket.Locked {
+ extra += " [locked]"
+ }
+ created := bucket.CreatedBy.Func.PkgDotName()
+ if created != "" {
+ created += " @ "
+ if fullPath {
+ created += bucket.CreatedBy.FullSourceLine()
+ } else {
+ created += bucket.CreatedBy.SourceLine()
+ }
+ extra += p.CreatedBy + " [Created by " + created + "]"
+ }
+ return fmt.Sprintf(
+ "%s%d: %s%s%s\n",
+ p.routineColor(bucket, multipleBuckets), len(bucket.Routines),
+ bucket.State, extra,
+ p.EOLReset)
+}
+
+// callLine prints one stack line.
+func (p *Palette) callLine(line *Call, srcLen, pkgLen int, fullPath bool) string {
+ src := ""
+ if fullPath {
+ src = line.FullSourceLine()
+ } else {
+ src = line.SourceLine()
+ }
+ return fmt.Sprintf(
+ " %s%-*s %s%-*s %s%s%s(%s)%s",
+ p.Package, pkgLen, line.Func.PkgName(),
+ p.SourceFile, srcLen, src,
+ p.functionColor(line), line.Func.Name(),
+ p.Arguments, line.Args,
+ p.EOLReset)
+}
+
+// StackLines prints one complete stack trace, without the header.
+func (p *Palette) StackLines(signature *Signature, srcLen, pkgLen int, fullPath bool) string {
+ out := make([]string, len(signature.Stack.Calls))
+ for i := range signature.Stack.Calls {
+ out[i] = p.callLine(&signature.Stack.Calls[i], srcLen, pkgLen, fullPath)
+ }
+ if signature.Stack.Elided {
+ out = append(out, " (...)")
+ }
+ return strings.Join(out, "\n") + "\n"
+}
diff --git a/vendor/github.com/maruel/panicparse/vendor.yml b/vendor/github.com/maruel/panicparse/vendor.yml
new file mode 100644
index 000000000..ff3d43f5f
--- /dev/null
+++ b/vendor/github.com/maruel/panicparse/vendor.yml
@@ -0,0 +1,17 @@
+vendors:
+- path: github.com/kr/pretty
+ rev: 737b74a46c4bf788349f72cb256fed10aea4d0ac
+- path: github.com/kr/text
+ rev: 7cafcd837844e784b526369c9bce262804aebc60
+- path: github.com/maruel/ut
+ rev: a9c9f15ccfa6f8b90182a53df32f4745586fbae3
+- path: github.com/mattn/go-colorable
+ rev: 9056b7a9f2d1f2d96498d6d146acd1f9d5ed3d59
+- path: github.com/mattn/go-isatty
+ rev: 56b76bdf51f7708750eac80fa38b952bb9f32639
+- path: github.com/mgutz/ansi
+ rev: c286dcecd19ff979eeb73ea444e479b903f2cfcb
+- path: github.com/pmezard/go-difflib
+ rev: 792786c7400a136282c1664665ae0a8db921c6c2
+- path: golang.org/x/sys
+ rev: a646d33e2ee3172a661fc09bca23bb4889a41bc8
diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go
index 52d6653b3..a7fe19a8c 100644
--- a/vendor/github.com/mattn/go-colorable/colorable_others.go
+++ b/vendor/github.com/mattn/go-colorable/colorable_others.go
@@ -7,6 +7,7 @@ import (
"os"
)
+// NewColorable return new instance of Writer which handle escape sequence.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
@@ -15,10 +16,12 @@ func NewColorable(file *os.File) io.Writer {
return file
}
+// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
func NewColorableStdout() io.Writer {
return os.Stdout
}
+// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
func NewColorableStderr() io.Writer {
return os.Stderr
}
diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go
index 448277f56..628ad904e 100644
--- a/vendor/github.com/mattn/go-colorable/colorable_windows.go
+++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go
@@ -75,6 +75,7 @@ type Writer struct {
oldpos coord
}
+// NewColorable return new instance of Writer which handle escape sequence from File.
func NewColorable(file *os.File) io.Writer {
if file == nil {
panic("nil passed instead of *os.File to NewColorable()")
@@ -90,10 +91,12 @@ func NewColorable(file *os.File) io.Writer {
}
}
+// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
func NewColorableStdout() io.Writer {
return NewColorable(os.Stdout)
}
+// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
func NewColorableStderr() io.Writer {
return NewColorable(os.Stderr)
}
@@ -357,6 +360,7 @@ var color256 = map[int]int{
255: 0xeeeeee,
}
+// Write write data on console
func (w *Writer) Write(data []byte) (n int, err error) {
var csbi consoleScreenBufferInfo
procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi)))
diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go
index b60801dcd..ca588c78a 100644
--- a/vendor/github.com/mattn/go-colorable/noncolorable.go
+++ b/vendor/github.com/mattn/go-colorable/noncolorable.go
@@ -5,15 +5,18 @@ import (
"io"
)
+// NonColorable hold writer but remove escape sequence.
type NonColorable struct {
out io.Writer
lastbuf bytes.Buffer
}
+// NewNonColorable return new instance of Writer which remove escape sequence from Writer.
func NewNonColorable(w io.Writer) io.Writer {
return &NonColorable{out: w}
}
+// Write write data on console
func (w *NonColorable) Write(data []byte) (n int, err error) {
er := bytes.NewReader(data)
var bw [1]byte
diff --git a/vendor/github.com/nsf/termbox-go/README.md b/vendor/github.com/nsf/termbox-go/README.md
index d152da407..e7c57a936 100644
--- a/vendor/github.com/nsf/termbox-go/README.md
+++ b/vendor/github.com/nsf/termbox-go/README.md
@@ -24,6 +24,7 @@ There are also some interesting projects using termbox-go:
- [snake-game](https://github.com/DyegoCosta/snake-game) is an implementation of the Snake game.
- [gone](https://github.com/guillaumebreton/gone) is a CLI pomodoro® timer.
- [Spoof.go](https://github.com/sabey/spoofgo) controllable movement spoofing from the cli
+ - [lf](https://github.com/gokcehan/lf) is a terminal file manager
### API reference
[godoc.org/github.com/nsf/termbox-go](http://godoc.org/github.com/nsf/termbox-go)
diff --git a/vendor/github.com/nsf/termbox-go/api.go b/vendor/github.com/nsf/termbox-go/api.go
index b339e532f..b242ddcf3 100644
--- a/vendor/github.com/nsf/termbox-go/api.go
+++ b/vendor/github.com/nsf/termbox-go/api.go
@@ -343,7 +343,6 @@ func PollEvent() Event {
return event
}
}
- panic("unreachable")
}
// Returns the size of the internal back buffer (which is mostly the same as
diff --git a/vendor/github.com/nsf/termbox-go/termbox.go b/vendor/github.com/nsf/termbox-go/termbox.go
index 6e5ba6c8f..c2d86c658 100644
--- a/vendor/github.com/nsf/termbox-go/termbox.go
+++ b/vendor/github.com/nsf/termbox-go/termbox.go
@@ -233,10 +233,7 @@ func send_char(x, y int, ch rune) {
func flush() error {
_, err := io.Copy(out, &outbuf)
outbuf.Reset()
- if err != nil {
- return err
- }
- return nil
+ return err
}
func send_clear() error {
diff --git a/vendor/github.com/pborman/uuid/README.md b/vendor/github.com/pborman/uuid/README.md
index f023d47ca..b0396b274 100644
--- a/vendor/github.com/pborman/uuid/README.md
+++ b/vendor/github.com/pborman/uuid/README.md
@@ -1,7 +1,7 @@
This project was automatically exported from code.google.com/p/go-uuid
# uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master)
-The uuid package generates and inspects UUIDs based on [RFC 412](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services.
+The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services.
###### Install
`go get github.com/pborman/uuid`
diff --git a/vendor/github.com/rcrowley/go-metrics/gauge.go b/vendor/github.com/rcrowley/go-metrics/gauge.go
index d618c4553..cb57a9388 100644
--- a/vendor/github.com/rcrowley/go-metrics/gauge.go
+++ b/vendor/github.com/rcrowley/go-metrics/gauge.go
@@ -44,7 +44,6 @@ func NewFunctionalGauge(f func() int64) Gauge {
return &FunctionalGauge{value: f}
}
-
// NewRegisteredFunctionalGauge constructs and registers a new StandardGauge.
func NewRegisteredFunctionalGauge(name string, r Registry, f func() int64) Gauge {
c := NewFunctionalGauge(f)
@@ -101,6 +100,7 @@ func (g *StandardGauge) Update(v int64) {
func (g *StandardGauge) Value() int64 {
return atomic.LoadInt64(&g.value)
}
+
// FunctionalGauge returns value from given function
type FunctionalGauge struct {
value func() int64
@@ -117,4 +117,4 @@ func (g FunctionalGauge) Snapshot() Gauge { return GaugeSnapshot(g.Value()) }
// Update panics.
func (FunctionalGauge) Update(int64) {
panic("Update called on a FunctionalGauge")
-} \ No newline at end of file
+}
diff --git a/vendor/github.com/rcrowley/go-metrics/registry.go b/vendor/github.com/rcrowley/go-metrics/registry.go
index 9086dcbdd..2bb7a1e7d 100644
--- a/vendor/github.com/rcrowley/go-metrics/registry.go
+++ b/vendor/github.com/rcrowley/go-metrics/registry.go
@@ -167,9 +167,9 @@ func NewPrefixedChildRegistry(parent Registry, prefix string) Registry {
// Call the given function for each registered metric.
func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
- wrappedFn := func (prefix string) func(string, interface{}) {
+ wrappedFn := func(prefix string) func(string, interface{}) {
return func(name string, iface interface{}) {
- if strings.HasPrefix(name,prefix) {
+ if strings.HasPrefix(name, prefix) {
fn(name, iface)
} else {
return
@@ -184,7 +184,7 @@ func (r *PrefixedRegistry) Each(fn func(string, interface{})) {
func findPrefix(registry Registry, prefix string) (Registry, string) {
switch r := registry.(type) {
case *PrefixedRegistry:
- return findPrefix(r.underlying, r.prefix + prefix)
+ return findPrefix(r.underlying, r.prefix+prefix)
case *StandardRegistry:
return r, prefix
}
diff --git a/vendor/github.com/rcrowley/go-metrics/sample.go b/vendor/github.com/rcrowley/go-metrics/sample.go
index 5f6a37788..fecee5ef6 100644
--- a/vendor/github.com/rcrowley/go-metrics/sample.go
+++ b/vendor/github.com/rcrowley/go-metrics/sample.go
@@ -33,7 +33,7 @@ type Sample interface {
// priority reservoir. See Cormode et al's "Forward Decay: A Practical Time
// Decay Model for Streaming Systems".
//
-// <http://www.research.att.com/people/Cormode_Graham/library/publications/CormodeShkapenyukSrivastavaXu09.pdf>
+// <http://dimacs.rutgers.edu/~graham/pubs/papers/fwddecay.pdf>
type ExpDecaySample struct {
alpha float64
count int64
@@ -302,6 +302,13 @@ type SampleSnapshot struct {
values []int64
}
+func NewSampleSnapshot(count int64, values []int64) *SampleSnapshot {
+ return &SampleSnapshot{
+ count: count,
+ values: values,
+ }
+}
+
// Clear panics.
func (*SampleSnapshot) Clear() {
panic("Clear called on a SampleSnapshot")
diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/session.go b/vendor/github.com/syndtr/goleveldb/leveldb/session.go
index f3e747701..ad68a8703 100644
--- a/vendor/github.com/syndtr/goleveldb/leveldb/session.go
+++ b/vendor/github.com/syndtr/goleveldb/leveldb/session.go
@@ -47,6 +47,7 @@ type session struct {
o *cachedOptions
icmp *iComparer
tops *tOps
+ fileRef map[int64]int
manifest *journal.Writer
manifestWriter storage.Writer
@@ -69,6 +70,7 @@ func newSession(stor storage.Storage, o *opt.Options) (s *session, err error) {
s = &session{
stor: stor,
storLock: storLock,
+ fileRef: make(map[int64]int),
}
s.setOptions(o)
s.tops = newTableOps(s)
diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go b/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go
index 34ad61798..92328933c 100644
--- a/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go
+++ b/vendor/github.com/syndtr/goleveldb/leveldb/session_util.go
@@ -39,6 +39,18 @@ func (s *session) newTemp() storage.FileDesc {
return storage.FileDesc{storage.TypeTemp, num}
}
+func (s *session) addFileRef(fd storage.FileDesc, ref int) int {
+ ref += s.fileRef[fd.Num]
+ if ref > 0 {
+ s.fileRef[fd.Num] = ref
+ } else if ref == 0 {
+ delete(s.fileRef, fd.Num)
+ } else {
+ panic(fmt.Sprintf("negative ref: %v", fd))
+ }
+ return ref
+}
+
// Session state.
// Get current version. This will incr version ref, must call
@@ -46,7 +58,7 @@ func (s *session) newTemp() storage.FileDesc {
func (s *session) version() *version {
s.vmu.Lock()
defer s.vmu.Unlock()
- s.stVersion.ref++
+ s.stVersion.incref()
return s.stVersion
}
@@ -59,14 +71,15 @@ func (s *session) tLen(level int) int {
// Set current version to v.
func (s *session) setVersion(v *version) {
s.vmu.Lock()
- v.ref = 1 // Holds by session.
- if old := s.stVersion; old != nil {
- v.ref++ // Holds by old version.
- old.next = v
- old.releaseNB()
+ defer s.vmu.Unlock()
+ // Hold by session. It is important to call this first before releasing
+ // current version, otherwise the still used files might get released.
+ v.incref()
+ if s.stVersion != nil {
+ // Release current version.
+ s.stVersion.releaseNB()
}
s.stVersion = v
- s.vmu.Unlock()
}
// Get current unused file number.
diff --git a/vendor/github.com/syndtr/goleveldb/leveldb/version.go b/vendor/github.com/syndtr/goleveldb/leveldb/version.go
index c60f12c20..73f272af5 100644
--- a/vendor/github.com/syndtr/goleveldb/leveldb/version.go
+++ b/vendor/github.com/syndtr/goleveldb/leveldb/version.go
@@ -34,44 +34,48 @@ type version struct {
cSeek unsafe.Pointer
- closing bool
- ref int
- // Succeeding version.
- next *version
+ closing bool
+ ref int
+ released bool
}
func newVersion(s *session) *version {
return &version{s: s}
}
+func (v *version) incref() {
+ if v.released {
+ panic("already released")
+ }
+
+ v.ref++
+ if v.ref == 1 {
+ // Incr file ref.
+ for _, tt := range v.levels {
+ for _, t := range tt {
+ v.s.addFileRef(t.fd, 1)
+ }
+ }
+ }
+}
+
func (v *version) releaseNB() {
v.ref--
if v.ref > 0 {
return
- }
- if v.ref < 0 {
+ } else if v.ref < 0 {
panic("negative version ref")
}
- nextTables := make(map[int64]bool)
- for _, tt := range v.next.levels {
- for _, t := range tt {
- num := t.fd.Num
- nextTables[num] = true
- }
- }
-
for _, tt := range v.levels {
for _, t := range tt {
- num := t.fd.Num
- if _, ok := nextTables[num]; !ok {
+ if v.s.addFileRef(t.fd, -1) == 0 {
v.s.tops.remove(t)
}
}
}
- v.next.releaseNB()
- v.next = nil
+ v.released = true
}
func (v *version) release() {